Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
fromoutofnowhere
Mar 19, 2004

Enjoy it while you can.
Thank you so much The Electronaut! After banging my head against the wall just giving the term "select" basically gave me what I needed to work out what I was doing.

Finished this today and will create the script to use this data to change the profiles later.

Get-ADUser -filter * -properties profilepath, homedirectory | select-object Name, profilepath, homedirectory | format-list > c:\temp\test1.csv
Get-content -path c:\temp\test1.csv | foreach-object {$_ -replace "\\Filenamex", "\\Filenamey"} | set-content c:\temp\test2.csv

edit: search - select, same thing. :(

fromoutofnowhere fucked around with this message at 15:19 on Jun 19, 2014

Adbot
ADBOT LOVES YOU

The Electronaut
May 10, 2009

fromoutofnowhere posted:

Thank you so much The Electronaut! After banging my head against the wall just giving the term "select" basically gave me what I needed to work out what I was doing.

Finished this today and will create the script to use this data to change the profiles later.

Get-ADUser -filter * -properties profilepath, homedirectory | select-object Name, profilepath, homedirectory | format-list > c:\temp\test1.csv
Get-content -path c:\temp\test1.csv | foreach-object {$_ -replace "\\Filenamex", "\\Filenamey"} | set-content c:\temp\test2.csv

edit: search - select, same thing. :(

Haha. Great! I've done something very similar and even have it saved off but I was out and about away from my repository so couldn't just paste bin. Something to concern yourself with longer term, the AD cmdlets kind of suck IMO and prefer to use LDAP for data gathering most of the time, same with the Exchange cmdlets that hit AD for their data.

12 rats tied together
Sep 7, 2006

Something to keep in mind is that you can take an array and just pipe it into ForEach-Object if you want to iterate through it. So, you probably don't even need to generate test1.csv or test2.csv - not that it really matters since you've already accomplished your goal/task, but it's kind of a sloppy habit (IMO) that I see everywhere when it comes to powershell.

You might have to play around with it a little, but generally you can do things like:

code:
Get-ADUser -filter * -properties * | ForEach-Object {
    
    if ($_.profilepath -notlike "\\Filenamey") {

        $_.profilepath = "\\Filenamey"
        }

    if ($_.homedirectory -notlike "\\Pathnamey") {

        $_.homedirectory = "\\Pathnamey"
        }

}
I try to think of problems in such a way that I use Powershell more like a shell and less like a scripting language. It's especially nice to be able to go "Some of these properties are set incorrectly, I will fix them" instead of "Some of these properties are set incorrectly, I will look at all of them, sort them into two separate CSVs, which I will then iterate through, do a find-replace on, and then write an entirely different script to import CSV text into AD objects/properties."

I actually just had this exact problem (sort of) about a month ago where our AD users' Extension Attribute was being set improperly by a (crappy) new user powershell script that someone had written a few years ago and nobody had any clue what was happening in it. My boss wanted me to set everyone's extension attribute (150+ people) to the number identified in the Sharepoint list that HR was keeping track of, and it was fairly easy. Invoke-WebRequest the sharepoint list, select -expand content, regex into an array containing Name,Extension. ForEach-Object, Get-ADUser where $_.name -like name, and then $_.extAttribute = Extension.

In general I feel like you lose a lot of the object oriented functionality (and convenience) of Powershell if you are constantly pounding everything out into a CSV. It's faster to write, easier to understand and maintain, and IMO just makes more sense if you use the framework that already exists instead of trying to brute force your way through yourself. I also notice that a lot of people seem to focus on Powershell's ability to Get the information they want, so they can then format it in some way, look at it, and then do something. Something I see a lot of people overlook is that powershell can actually do the Getting, Looking, and Doing for you - I actually consider Format-Table/List (ft,fl) and Out-GridView to be mostly useless for this reason. If the task is so simple that I am going to be manually completing a part of it, I can just look up the information myself. If looking up the information is too time consuming, I script the entire process.

CLAM DOWN
Feb 13, 2007




I wish there was a way to use the PS 4.0 SMB cmdlets in Server 2008 R2, I'm going nuts trying to incorporate net share or subinacl into my script :(

Mr Crucial
Oct 28, 2005
What's new pussycat?
I'm trying to user Powershell to set permissions on an OU in AD. I can set the permissions on the OU itself just fine, however I need them to also apply to all descendent objects as well, and they do not. I can't for the life of me figure out how to do it. Here's my code:

code:
# Get domain root
$global:RootDse = [ADSI] "LDAP://RootDSE"
$global:DefaultNamingContext = $RootDse.defaultNamingContext

# Get admin group SID
$admingroup = Get-ADGroup Test_Admins
$adminsid = new-object System.Security.Principal.SecurityIdentifier $admingroup.SID

# Get OU path including domain root
$ou = "AD:\OU=Test,$($RootDse.defaultNamingContext)"

# Get current ACL
$acl = get-acl $ou

# Add new ACE to ACL
# I think this is the bit failing, I don’t understand how you set this to ‘all child objects’
$ace = new-object System.DirectoryServices.ActiveDirectoryAccessRule $adminsid,'GenericAll','All',’Allow’
$acl.AddAccessRule($ace)

# Write ACL back to OU
set-acl -aclobject $acl $ou

I've trawled the internet for ages looking at examples but none seem to work, System.DirectoryServices.ActiveDirectoryAccessRule apparently allows you to do this but my Powershell command fails whenever I add extra arguments for inheritance.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I am trying to do some authentication for file shares cleanly and compactly. Say I could have a tedious number of remote machines with a common file share structure to which I want to manage some files. These machines can have different logins, although most are the same. I was hoping there was an easy way to only prompt for credentials the first time I need to use a different login. So there may be 20 machines I can login to using login/password ABC/123, and 30 more than do XYZ/789. I was hoping to at most only get two prompts in that case for the login credentials. I'd also hope to hide the password. Is there a way I can get into that without having to try New-PSDrive then react if there's a login problem?

12 rats tied together
Sep 7, 2006

Rocko Bonaparte posted:

I am trying to do some authentication for file shares cleanly and compactly. Say I could have a tedious number of remote machines with a common file share structure to which I want to manage some files.

The easiest way to do this would probably involve Try, Catch. You can assign the credentials to two variables, do a try { do-thing $credentials_1 } catch { do-thing $credentials_2 }. You'll probably have to fiddle with the catch, it doesn't always catch like I expect it to, but to be fair I almost never use it.

Another way would be to separate the servers out, if they aren't changing dynamically or anything. You have two arrays, each one contains a series of hostname strings for each set of credentials. $array_credentials1 | ForEach-Object { Do-Thing -action -computername $_ }; $array_credentials2 | ForEach-Object {Do_Thing -action -computername $_ }.

If the password changes dynamically but is stored in say, a spreadsheet somewhere? Or maybe a sharepoint list? SQL database? You can get the content of that location with Get-Content, System.Data.SqlClient.SqlCommand, or Invoke-WebRequest, and then regex it and grab the password. With CSVs, you can do Import-CSV to generate objects based on the CSV, etc.

So the simple answer is that there are a lot of ways to do this but it depends on what you're doing and how you get the credentials. I could provide better suggestions with some more info. However, I would also be somewhat concerned that you would need to use two logins for anything at all. Some background on the logins, specifically, would also be useful. You can also use test-path to generate a true/false for your current access rights to a location - it would be pretty easy to do a if $access -eq $true { do thing }, else { do-thing -with other credentials }.

quote:

I'm trying to user Powershell to set permissions on an OU in AD. I can set the permissions on the OU itself just fine, however I need them to also apply to all descendent objects as well, and they do not. I can't for the life of me figure out how to do it.
Admittedly, I've never tried to do this. However, I'd be interested in seeing any error messages you get when you run $acl.AddAccessRule($ace). I feel like your formatting is off when you are constructing the class. In particular, if you take a look at the constructor page: click

code:
System.DirectoryServices.ActiveDirectoryAccessRule(IdentityReference, ActiveDirectoryRights, AccessControlType, ActiveDirectorySecurityInheritance) 
$adminsid,     - identifier that points to SID of group in question
'GenericAll',  - the rights you are assigning, in this case basically full permissions
'All',         - this should be a System.Security.AccessControl, basically allow/deny the permission GenericAll to the object identified in $adminsid
’Allow’        - this should be an ActiveDirectorySecurityInheritance enumeration, you probably want All or SelfAndChildren depending
               - the quotes surrounding 'allow' in your example are kind of odd, also.  is that an explicit single endquote? 
It's also possible that GenericAll isn't setting the permissions properly, but that would depend on the permissions of the context that you are running powershell in and whether or not you are modifying that context's permissions with powershell. For example, if you removed your ability to set permissions on the child objects while playing around with an earlier script, you would probably have some difficulty re-setting them without using another, more privileged account.

12 rats tied together fucked around with this message at 08:19 on Jul 11, 2014

ElGroucho
Nov 1, 2005

We already - What about sticking our middle fingers up... That was insane
Fun Shoe
Can somebody tell me what I'm doing wrong here? I'm trying to write a script that creates a DL and adds members all at once.

code:
$dl_name = Read-Host "Enter the name of the distribution list: "
$manager = Read-Host "Enter the manager's name: "

New-DistributionGroup -Name $dl_name -OrganizationalUnit "company.com/_Resources/DL.InAddressBook" `
-ManagedBy $manager -alias $dl_name -PrimarySmtpAddress ($dl_name + "@company.com")

Import-Csv .\members.csv | foreach {Add-DistributionGroupMember -Identity $dl_name -Member $_.member}
If i run New-DistributionGroup and Import/Add seperately, they both work fine, but in the same script, it won't add anything because "object DL.Test couldn't be found on AD.company.com"
I've tried adding a start-sleep to give it time to create the DL, still no good.

EDIT:

Ignore this dumb post, added a do...while to check for existence.

ElGroucho fucked around with this message at 20:10 on Jul 11, 2014

AlternateAccount
Apr 25, 2005
FYGM
I am trying to import a CSV of AD users and related data, then do a compare against existing data, make a change if required and the log it out to a text file. It's fairly trivial to just blanket overwrite everything with the CSV data, but I'd rather do a compare and handle it a bit more gracefully.
I can never get IF statements to work well in this context, if at all, is this a limitation that exists when using Import-CSV?

12 rats tied together
Sep 7, 2006

Without being able to see your script and any of the error messages, I would say the most common mistake I see people making with Import-CSV is that it constructs objects based on the text file, so you probably need to dot source based on the array index variable. For example if you're doing in the compare in a for-loop it should look something like:

(this is clunky for clarity's sake)
code:
$CSV_Users = Import-CSV c:\users.txt

$CSV_Users | ForEach-Object {

    $CurrentProperty = Get-ADUser $_.Name -properties * | select property
    $CSVProperty = $_.Property
    
        if ($CurrentProperty -notlike $CSVProperty) {
            Set-ADUser -identity $_.Name -Property $CSVProperty
            }
}
I'd be able to say more with some more information, but I can also confirm that If/While/For etc all work perfectly fine for me with dealing with import-csv, or custom/dynamic objects in general. The only thing I've noticed is that sometimes (seems to depend on command, and if you're nested in a function, and if intellisense feels like it, and if a string is involved), dot sourcing in parameters gets funky. Like, I'll do a Get-Filehash -path $_.FullName to drop in the full filepath of the current object I'm working with, and in some situations I'll get an error message that "c:\scripts\thing.txt.FullName" isn't a valid filepath.

I wanna say, usually when I see this kind of error I'm trying to do something with Invoke-Command and run it remotely on several computers at once. Generally, I fix it by by specifically assigning sub-variables (such as $CurrentProperty = $_.Property), which I think is pretty sloppy. Other times I'll just realize that what I'm trying to do is stupid and do it some other, better way.

Mr Crucial
Oct 28, 2005
What's new pussycat?

Reiz posted:

Admittedly, I've never tried to do this. However, I'd be interested in seeing any error messages you get when you run $acl.AddAccessRule($ace). I feel like your formatting is off when you are constructing the class. In particular, if you take a look at the constructor page: click

You're right, I'd accidentally posted one of my attempts that didn't actually work. The line that does work is:

code:
$ace = new-object System.DirectoryServices.ActiveDirectoryAccessRule $adminsid,'GenericAll','Allow'
That sets the permission but applies it to the OU only, not the child objects. The error I get is to do with the number of parameters being incorrect when I tried to add extra ones (not in front of my machine atm so I don't have the exact error to hand.

I think I'm doing something fundamentally wrong here, because when I look at the results of Get-ACL when the permission is applied to child objects and when it's not, the ACL is in fact identical. So I wonder if there's another command that sets inheritance.

TheEffect
Aug 12, 2013
Dumb question:

I know that when specifying a directory for a variable, in order to go up one directory you just type ".\" in front of the directory name ($LogPath = ".\Logs"), but what if I want to go up two directories?

FISHMANPET
Mar 3, 2007

Sweet 'N Sour
Can't
Melt
Steel Beams
To up one level you would go to .. so in your example it would be $LogPath = "..\Logs". To go up two levels just keep doing the same, "..\..\Logs" etc etc.

TheEffect
Aug 12, 2013

FISHMANPET posted:

To up one level you would go to .. so in your example it would be $LogPath = "..\Logs". To go up two levels just keep doing the same, "..\..\Logs" etc etc.

Thank you for this. It works just fine when I run it in the PS ISE, but when I run it the way I'm trying to get it to work I get a "directory not found error". I'm confused as to why this is.

Edit- Ok, so it looks like ..\..\ was bringing me up one more than I wanted. "..\" works perfectly to go up two, and for one directory ".\" works. Did I interpret your answer wrong?

I'm going about this in a bit of a convoluted way-

I have a VB.net Windows Form GUI that kicks off a batch file that then kicks off a PS script.

VB snippet-
code:
    Private Sub copyBTN_Click(sender As Object, e As EventArgs) Handles copyBTN.Click
        Shell(path & "\Resources\FilePush\Current\FilePushKicker.bat", vbNormalFocus)
    End Sub
Batch-
code:
@ECHO OFF
title FilePush Kicker
SET ScriptDirectory=%~dp0
SET ScriptPath=%ScriptDirectory%FilePush_V0.5.ps1
PowerShell -NoProfile -ExecutionPolicy Unrestricted -Command "& {Start-Process PowerShell
 -ArgumentList '-NoProfile -ExecutionPolicy Unrestricted -File ""%ScriptPath%""' -Verb RunAs}";
PS snippet-
code:
$ScriptLocation = Split-Path -Parent $MyInvocation.MyCommand.Definition
$ScriptRunPath = Split-Path -Path $ScriptLocation -Parent 
Set-Location "$ScriptRunPath"
...
$LogPath = "..\..\Logs"
$ErrorLog = Join-Path $LogPath $ErrorLogName
...
Function OutputToError
{
    $Input | %{Write-Host $_; Out-File -FilePath $ErrorLog -InputObject $_ -Append}
}
...
*Here's where it breaks (I think)*
Try 
{ 
	"====================================================" | OutputToError
}
Any ideas?

TheEffect fucked around with this message at 21:13 on Jul 24, 2014

capitalcomma
Sep 9, 2001

A grim bloody fable, with an unhappy bloody end.
I'm missing something very, very obvious.

How do I return values from Powershell functions?

code:
function StoreThisVariable
{
    $a = "Hello World!"
}

StoreThisVariable
Write-Host $a
This produces a blank line: the script is not aware of the variable $a. I'm assuming that the function makes $a, then discards it as soon as the function is completed.

I have functions that need to return certain info, including variables, for use in the rest of the script. What change would I need to make to the above script to print "hello world!"?

Fenrisulfr
Oct 14, 2012
code:
function StoreThisVariable
{
    Return "Hello World!"
}

$a = StoreThisVariable
Write-Host $a

capitalcomma
Sep 9, 2001

A grim bloody fable, with an unhappy bloody end.
That did it! Thank you. Some of the articles on "return in powershell" were misleading about how return works and doesn't work, and totally pointed me in the wrong direction.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

TheEffect posted:

Edit- Ok, so it looks like ..\..\ was bringing me up one more than I wanted. "..\" works perfectly to go up two, and for one directory ".\" works. Did I interpret your answer wrong?

Let's say you're in C:\Foo\Bar\Baz\

. = C:\Foo\Bar\Baz\
.\.. = C:\Foo\Bar\
.\..\.. = C:\Foo\
etc

"." is the current directory, not "up" anything.

IAmKale
Jun 7, 2007

やらないか

Fun Shoe
What's the proper way to grab a field from an array when the key is a string? For example:

code:
$cols = @()
$items = @("Title", "Code")

foreach($col in $cols)
{
    $cols += @{Name=$col;expression={$_[$col];}}
}
Unfortunately, this is what I get back:

code:
Name                           Value                                                                            
----                           -----                                                                            
expression                     $_[$col];
Name                           Title
expression                     $_[$col];
Name                           Code
What I want is this:
code:
Name                           Value                                                                            
----                           -----                                                                            
expression                     $_["Title"];
Name                           Title
expression                     $_["Code"];
Name                           Code

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Karthe posted:

What's the proper way to grab a field from an array when the key is a string? For example:

It's not clear what your end goal is here... Arrays and associative arrays are different things. Your sample code doesn't even reproduce the problem you're talking about.

[edit]
Is this what you're after?

code:
$items = @("Title", "Code")
$cols = @()

foreach($col in $items)
{
    $cols += @{Name=$col;expression="`$_[`"$col`"];"}
}

$cols
Output:
code:
Name                           Value
----                           ----- 
expression                     $_["Title"];
Name                           Title 
expression                     $_["Code"];
Name                           Code         
I suspect you actually are looking for something more like:
code:
$things = @(
            @{Title="Butts"; Code="Dongs"},
            @{Title="Foo"; Code="Bar"},
            @{Title="Baz"; Code="Etc"}
        )
so you can filter/project the items based on the keys, like:
code:
$things | where { $_.Title -eq "Foo" }

New Yorp New Yorp fucked around with this message at 03:39 on Jul 25, 2014

IAmKale
Jun 7, 2007

やらないか

Fun Shoe
Sorry, I should have realized the code would be too ambiguous. What I'm trying to do is export some lists from Sharepoint into a CSV file. Right now I'm trying to make a single function that is flexible enough to take a List name, identifier for the CSV file, and a list of FieldValues and produce the desired CSV file.

Here's a more thorough bit of code:

code:
function getListData($_ctx, [string]$_colName)
{
	$list = $_ctx.Web.Lists.GetByTitle("$_colName")

	$camlQuery = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(100)
	$colItems = $list.GetItems($camlQuery)
	$_ctx.Load($colItems)
	$_ctx.ExecuteQuery();

	return $colItems
}

# More will go into this array, but for now a single entry is sufficient for testing purposes
$mstLists = @("GroupMst", "Groups", @("Title", "GroupCode"))

$cols = @()
foreach($col in $mstLists[0][2])
{
    $cols += @{Name=$col;expression={$_[$col];}}
    $col
}
$cols

# Grab all items from a list
getListData $ctx $mstLists[0][0] |
%{ select-object -input $_ -prop $cols } |
    Export-Csv -Path ($export_path + '\' + $current_date + '_' + $mstLists[0][1] + '.csv') -Encoding UTF8 -NoTypeInformation
And here's the current CSV output:

pre:
"Title","GroupCode"
"LA","LA"
"NY","NY"
"TK","TK"
It should look like this based on information that's currently in the List retrieved from Sharepoint (I know the field values are correct):
pre:
"Title","GroupCode"
"Los Angeles","LA"
"New York","NY"
"Tokyo","TK"
I need each entry in $cols to look like @{Name="Title";expression={$_["Title"];}} for the select-object to format the info correctly. It's the best way (thus far) that I've found to extract the desired values from each List item and get them into a proper CSV file. If I hardcode in values like "Title" and "GroupCode" then the above code works; however I'm trying to avoid that in order to make this as flexible as possible.

For thoroughness sake, here's code that produces the desired result:

code:
# Grab all items from a list
getListData $ctx $mstLists[0][0] |
%{ select-object -input $_ -prop `
@{Name="Title";expression={$_["Title"];}}, `
@{Name='GroupCode';expression={$_["GroupCode"];}}; } |
    Export-Csv -Path ($export_path + '\' + $current_date + '_' + $mstLists[0][1] + '.csv') -Encoding UTF8 -NoTypeInformation

IAmKale fucked around with this message at 15:07 on Jul 25, 2014

TheEffect
Aug 12, 2013

Ithaqua posted:

Let's say you're in C:\Foo\Bar\Baz\

. = C:\Foo\Bar\Baz\
.\.. = C:\Foo\Bar\
.\..\.. = C:\Foo\
etc

"." is the current directory, not "up" anything.

I see. Thank you for explaining something so simple to this newbie.

Hughmoris
Apr 21, 2007
Let's go to the abyss!
In PowerShell, how do I loop through a text file and insert "Sleep(500)" in between each line?

I have text files that contain AutoIt Recorder code, and I want to pause .5 seconds between each block of code. I know I could learn to do it with AutoIt but I'm curious as to what it would look like in PowerShell.

Ithaqua posted:

Let's say you're in C:\Foo\Bar\Baz\

. = C:\Foo\Bar\Baz\
.\.. = C:\Foo\Bar\
.\..\.. = C:\Foo\
etc

"." is the current directory, not "up" anything.

I definitely didn't know that. Thank you.

Hughmoris fucked around with this message at 18:43 on Jul 25, 2014

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Hughmoris posted:

In PowerShell, how do I loop through a text file and insert "Sleep(500)" in between each line?

I have text files that contain AutoIt Recorder code, and I want to pause .5 seconds between each block of code. I know I could learn to do it with AutoIt but I'm curious as to what it would look like in PowerShell.


get-content .\test.txt | % { $_ + [System.Environment]::NewLine +"Sleep(500)" } | set-content .\output.txt

Hughmoris
Apr 21, 2007
Let's go to the abyss!

Ithaqua posted:

get-content .\test.txt | % { $_ + [System.Environment]::NewLine +"Sleep(500)" } | set-content .\output.txt

Thank you for this.

Coming from kicking Python around, that all looks very confusing. But I'm getting its like any language, once you get exposed to it a little bit it all makes sense

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Hughmoris posted:

Thank you for this.

Coming from kicking Python around, that all looks very confusing. But I'm getting its like any language, once you get exposed to it a little bit it all makes sense

I'll break it down:

code:
get-content .\test.txt 
This opens up test.txt and reads the contents in, no surprises there.

code:
| % 
The pipe character "|" takes the results of the previous command and passes it along to the next command. "%" is short-hand for "foreach". So for each line that we pulled out of test.txt, we're going to do something to it.

code:
{ $_ + [System.Environment]::NewLine +"Sleep(500)" } 
This is the block of logic we're executing on each line. "$_" is basically "the item in our current iteration of the foreach".

So for every line ($_), we're appending [System.Environment]::NewLine (a .NET thing that just maps to \r\n or \n, depending on OS), then appending the "Sleep(500)" text to that.

code:
| set-content .\output.txt
Then when we're done, pipe all of that transformed junk into a new file called output.txt.

Hughmoris
Apr 21, 2007
Let's go to the abyss!

Ithaqua posted:

I'll break it down:

code:
get-content .\test.txt 
This opens up test.txt and reads the contents in, no surprises there.

code:
| % 
The pipe character "|" takes the results of the previous command and passes it along to the next command. "%" is short-hand for "foreach". So for each line that we pulled out of test.txt, we're going to do something to it.

code:
{ $_ + [System.Environment]::NewLine +"Sleep(500)" } 
This is the block of logic we're executing on each line. "$_" is basically "the item in our current iteration of the foreach".

So for every line ($_), we're appending [System.Environment]::NewLine (a .NET thing that just maps to \r\n or \n, depending on OS), then appending the "Sleep(500)" text to that.

code:
| set-content .\output.txt
Then when we're done, pipe all of that transformed junk into a new file called output.txt.

Thanks for breaking everything down. I've been flipping through the book and I'm thinking my needs will be better suited by AutoIt. I won't be doing much administration tasks but rather testing and the sorts that involve recording mouse movements and keystrokes. I'll definitely keep the book on the shelf though.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Hughmoris posted:

Thanks for breaking everything down. I've been flipping through the book and I'm thinking my needs will be better suited by AutoIt. I won't be doing much administration tasks but rather testing and the sorts that involve recording mouse movements and keystrokes. I'll definitely keep the book on the shelf though.

Automated testing? Use an actual testing framework. Coded UI records your actions, translates them to .NET code, and lets you play them back. Then you can integrate it into a build/deploy process, especially if you use MTM for managing test cases.

Hughmoris
Apr 21, 2007
Let's go to the abyss!

Ithaqua posted:

Automated testing? Use an actual testing framework. Coded UI records your actions, translates them to .NET code, and lets you play them back. Then you can integrate it into a build/deploy process, especially if you use MTM for managing test cases.

I'm diving headfirst into this new job and am probably not explaining myself correctly. I work in informatics at a hospital and I'm testing software that our nurses use to chart on patients. The software is made by McKesson.

For my testing, I essentially open up a form, click/check/radio multiple options (sometimes random), then click SUBMIT. Afterwards I read over it and see if there are any weird errors or issues. AutoIt makes it very simple to record my mouse movement and clicks but it definitely isn't great because each form is different and each selection box may be in a different spot. Is that something I could attack with a different solution?

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Hughmoris posted:

I'm diving headfirst into this new job and am probably not explaining myself correctly. I work in informatics at a hospital and I'm testing software that our nurses use to chart on patients. The software is made by McKesson.

For my testing, I essentially open up a form, click/check/radio multiple options (sometimes random), then click SUBMIT. Afterwards I read over it and see if there are any weird errors or issues. AutoIt makes it very simple to record my mouse movement and clicks but it definitely isn't great because each form is different and each selection box may be in a different spot. Is that something I could attack with a different solution?

I don't understand why you'd be testing a vendor's software. That's the vendor's job. If their poo poo doesn't work right, tell them.

That said, give Coded UI a shot if you have access to a Visual Studio SKU that supports it. It might be able to read the IDs of all of the controls, although it's a crapshoot.

TheEffect
Aug 12, 2013

Ithaqua posted:

I don't understand why you'd be testing a vendor's software. That's the vendor's job. If their poo poo doesn't work right, tell them.

I agree with you 100%, the vendor should be during their due diligence, but we find so many bugs during our UAT process (which is painstakingly boring and repetitive) that it's not safe for us to deploy new software without first making sure it's 100% fit for use and there won't be any adverse client, or internal, impact. We're talking major vendors too.

wwb
Aug 17, 2004

Does their software have the windows accessiblity hooks built in? Is it keyboard operable? Sendkeys is fun and easy and the way we used to do this poo poo before we had newfangled crap like coded ui.

Hughmoris
Apr 21, 2007
Let's go to the abyss!

Ithaqua posted:

I don't understand why you'd be testing a vendor's software. That's the vendor's job. If their poo poo doesn't work right, tell them.

That said, give Coded UI a shot if you have access to a Visual Studio SKU that supports it. It might be able to read the IDs of all of the controls, although it's a crapshoot.

We have the ability to build and customize forms based on the framework that the software creator provided us. After creating or customizing a form, we test it in a train environment before sending it out to Live. This is my first job in this capacity so I'm not sure if its the norm or not, especially for healthcare.

I don't currently have access to Visual Studio and I think I'd raise a few eyebrows if I asked for it. None of the coworkers in my office automate anything, mainly from lack knowledge I'm guessing. They are open to it though. They really enjoyed seeing how fast AutoIt could complete some of our mundane tasks.

wwb posted:

Does their software have the windows accessiblity hooks built in? Is it keyboard operable? Sendkeys is fun and easy and the way we used to do this poo poo before we had newfangled crap like coded ui.

I'm not sure. I'd get blank looks if I asked anyone I have access to. I'm new, and testing/automating is a small part of my responsibilities so I don't want to come off as overzealous yet. However, poking around it looks like the coding for the iforms we use are in html and javascript.

Didn't mean to hijack the powershell thread but I appreciate the inputs.

Hughmoris fucked around with this message at 15:50 on Jul 29, 2014

wwb
Aug 17, 2004

If you can get the forms to work in a browser then that is easier -- check out http://docs.seleniumhq.org/ for a good tool.

AlternateAccount
Apr 25, 2005
FYGM

Reiz posted:

Without being able to see your script and any of the error messages, I would say the most common mistake I see people making with Import-CSV is that it constructs objects based on the text file, so you probably need to dot source based on the array index variable. For example if you're doing in the compare in a for-loop it should look something like:

You got me on the right path to getting this sorted, thank you very much.



Now, I am trying to rig up a way to automatically remove all disabled accounts from the address lists in Exchange, and this works just fine EXCEPT it also hides all the conference rooms as well.

code:
Get-Mailbox -resultsize unlimited | where {$_.ExchangeUserAccountControl -eq 'AccountDisabled'} | Set-Mailbox -HiddenFromAddressListsEnabled $true
Is there a smart way to exclude them?

wwb
Aug 17, 2004

You can chain wheres so if there is a way to say "where name not like conference-room-xxx" or something like that you'd be golden. No idea if there is an effective naming convention you can leverage.

Another idea would be to add a piece of metadata to cover "accounts that are disabled but should not be hidden" and then filter on that. Would probably be better than relying upon naming conventions.

AlternateAccount
Apr 25, 2005
FYGM
So I could have it work like:

Get-Mailbox Blah Blah | Where Account is Disabled | Where account does NOT have "Conference" in the name | Remove it from the lists

That sort of chaining works?

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
That works, though I don't see why you'd need to do that when you could just use -and.
code:
Get-Mailbox -resultsize unlimited | where {$_.ExchangeUserAccountControl -eq 'AccountDisabled' -and $_.Name -notlike '*Conference*'} | Set-Mailbox -HiddenFromAddressListsEnabled $true

dox
Mar 4, 2006
Bizarre question. I am trying to use Powershell to search HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\ for a Registry Key (folder?) with a Display Name of “HP Theft Recovery” and then delete that key. Is this even possible?

Back story is that I have an HP bloatware removal script that uses msiexec to uninstall the software, but Theft Recovery remains with a broken uninstaller in the Programs list that I'd like to remove... unfortunately the folder name changes with the GUID but the display name within the key always remains the same.

Edit:

Figured it out.

Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | ? {$_.GetValue('DisplayName') -match 'HP Theft Recovery'} | Remove-Item

dox fucked around with this message at 04:37 on Aug 1, 2014

Adbot
ADBOT LOVES YOU

capitalcomma
Sep 9, 2001

A grim bloody fable, with an unhappy bloody end.
Once again stuck on something very simple. I'm trying to remotely execute an MSI installer on a remote computer.

code:
Invoke-Command -computername COMPUTER -scriptblock { msiexec /i \\fileserver\share\asdf.msi /qn }
Running this from my workstation to a remote computer silently fails.

However, running the exact same command locally on the target computer works.

code:
Invoke-Command -scriptblock { msiexec /i \\fileserver\share\asdf.msi }
Can't see anything in event viewer to clue me in to what's going on. All the googling says remotely executing msi files, or batch files, is trivially easy, but I've followed a hundred tutorials to no avail. What am I missing?

capitalcomma fucked around with this message at 18:37 on Aug 2, 2014

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply