A slightly philosophical question: What is the verb to use, if you want to set some implicit state/defaults for subsequent commands to act on? Is that even a "sanctioned" idiom in Powershell? The specific case is that I'm working on a module to manage a set of application config files (XML), where you may need to add, remove, and modify items inside. I currently read the files, convert the items from the XML representation to simple .NET objects (defined as C# classes), and have some tools to work on those. Then a few commands to update the config files with the new objects. The commands that read/write from files takes parameters to indicate the files to work on, and I have defaults for the cmdlets set up to use the most common config file set. The idea I have is writing a command that sets some implicit state to control which config file set the other commands will work on, if the file parameters aren't given on each command. Command names I have considered: Select-FooConfig - bad, since Select is supposed to be used to pick out elements from a collection, not change state Enter-FooConfig - seems reasonable, but only common command is Enter-PSSession which effectively changes the entire environment, also implies a stack of states Push-FooConfig - seems reasonable, main sample is Push-Location which is less whole-environment affecting than Enter-PSSession, also implies a stack of states Use-FooConfig - maybe? not really any commands I know of that use it Set-FooConfig - not really, since it doesn't change any permanent state by itself
|
|
# ¿ Dec 10, 2015 13:08 |
|
|
# ¿ Apr 29, 2024 01:24 |
Zaepho posted:Have you thought about New-FooConfig You're creating a Configuration object of some sort to pass to all the other Foo cmdlets. like a DB Connection object. Not quite... my intention is to have it be implicit state, similar to the current directory. Edit: On the other hand, the command aliased to "cd" is Set-Location which doesn't really do permanent state changes either. So maybe Set-FooCurrentConfig would be it. nielsm fucked around with this message at 15:31 on Dec 10, 2015 |
|
# ¿ Dec 10, 2015 15:28 |
Briantist posted:I would recommend not storing state in your own variable or whatever. That's not really done in powershell for the most part. When you think about something like Push-Location, it's really modifying the state of the system (at least the current environment; by changing the working directory), so it's not limited to a script. That's a really good point, and since the config filename parameters I'm already taking have quite unique names, it wouldn't clash with other things either, even if I use wildcard command names in the $PSDefaultParameterValues hash. Thanks.
|
|
# ¿ Dec 10, 2015 18:22 |
Okay another question, regarding the same module. I'm having trouble making my Get-FooItems command take either name, id, or nothing, and also have a "comfortable" syntax.code:
pre:SYNTAX Get-FooItems [-FooConfigFile <string>] [<CommonParameters>] Get-FooItems -Id <int[]> [-FooConfigFile <string>] [<CommonParameters>] Get-FooItems [-Name] <string[]> [-FooConfigFile <string>] [<CommonParameters>] Works: pre:Get-FooItems # gets all Get-FooItems -Id 1234 # gets a single id Get-FooItems -Id 123,456 # gets multiple id's Get-FooItems -Name abcd # gets by a single name Get-FooItems -Name abc,def # gets by multiple names 123,456,789 | Get-FooItems # gets multiple id's "abc","def","ghi" | Get-FooItems # gets by multiple names pre:Get-FooItems abc # (A) expected to work, get items by single name Get-FooItems 123 # (B) not expected to work, get item by id Get-FooItems abc,def # (C) expected to work, get items by multiple names Get-FooItems 123,456 # (D) not expected to work, get items by multiple id's Get-FooItems abc def # (E) expected to work, get items by multiple names Get-FooItems 123 456 # (F) not expected to work, get items by multiple id's Get-FooItems -Name abc def # (G) expected to work, get items by multiple names Get-FooItems -Id 123 456 # (H) expected to work, get items by multiple id's However cases A, C and E should work, since the Name parameter is positional, the FooConfigFile parameter is not positional, and the -Name flag is supposed to be optional (per the generated help). Cases G and H should work with values specified as further arguments, since both Id and Name parameters are specified as ValueFromRemainingArguments. Shouldn't they then take any later positional arguments?
|
|
# ¿ Dec 11, 2015 11:28 |
Briantist posted:This is a tough one. The parameter binding process sometimes seems to bind things in unexpected ways which leads to ambiguity where there appears to be none. This is compounded by pipeline support, ValueFromRemainingArguments, multiple parameter sets, and positional binding, and you've combined them all! The 3 parameter sets the help shows is as intended, yes. The internal handling differs quite a lot depending on whether I need to get all items, filter by name, or fetch by id, so being able to test on $PSCmdlet.ParameterSetName makes the implementation simpler and easier to follow. The config file is always needed, since that's where it fetches the data from. ValueFromRemainingArguments is not strictly necessary, I just thought it would be neat if you could filter by multiple names or fetch multiple id's without worrying about commas. But it seems to be more trouble than it's worth, so I may as well scrap it. Pipeline support also isn't strictly needed, at least not for the Name parameter. It seems most relevant for the Id parameter, although I'm not sure if there are any use cases for that either. The most important case of the failed ones is A, and I don't understand why it fails. There should be exactly one possible call of the function that takes one positional parameter, and that's the "Name" parameter set.
|
|
# ¿ Dec 14, 2015 22:52 |
Swink posted:I want to: Parenthesize the command in the if statement and pull out the property from that: code:
|
|
# ¿ Dec 29, 2015 13:12 |
If you're on PowerShell 3 or later, this part:code:
code:
code:
The old version compatible syntax would be: code:
Doing that allows you to simplify the following two lines to: code:
How about this? code:
|
|
# ¿ Jan 11, 2016 18:14 |
beepsandboops posted:Interesting! I didn't know about filter script. I can't find much about it in Microsoft's official documentation though. Is it an alias for something else? It's a filter function, placed in the "script" namespace. The "filter" keyword introduces a filter function. A filter function is pretty much a shortcut to write a full function, that only has a Process block, and implicitly takes a single pipeline input, and produces pipeline output. They're a simple way to wrap sub-operations you want to either name, or maybe re-use. The "script:" part is a qualifier that ties to the "Where-MailboxIsOld" name. I'm honestly not entirely sure about it, but it's supposed to place the function in the script namespace, meaning it wouldn't get exported if you load the script as a module, or source it in an interactive session. The rest of it is effectively a Process block inside a function, meaning the body of the filter function gets executed once for every item in the input pipeline. Because of that, it should also be possible to write it with an if statement, that then only outputs the mailbox back out if it's sufficiently aged. Something else is, consider having PS 4 or 5 on your workstation, and then set up a remoting session to your Exchange server. It's much more convenient, lets you work on Exchange through a local PS window, or even use the ISE, without having to open a remote desktop to another machine, or even having the Exchange management tools installed. nielsm fucked around with this message at 22:28 on Jan 13, 2016 |
|
# ¿ Jan 13, 2016 22:26 |
I don't think there is. Instead, you can try matching the entire filename into three match groups, a prefix, the number, and a suffix, with an if ($x -match "re"). Then use the match groups to reconstruct the new filename and perform the rename.
|
|
# ¿ Jan 15, 2016 23:30 |
nm do the above
|
|
# ¿ Jan 26, 2016 22:32 |
FISHMANPET posted:I think the author of the cmdlet has to write in support for -whatif, so that command just does it poorly. Are you having actual roubles executing the command, and/or is there a reason you're not using Disable-NetAdapterVmq? Do that if it's all you need to do. Apart from that, the parameter is called "-enabled". I think -WhatIf is dependent on the implementation having confirmation checks. In WhatIf mode it'd then just print the step to be confirmed, and continue as if the user rejected. nielsm fucked around with this message at 22:35 on Feb 4, 2016 |
|
# ¿ Feb 4, 2016 22:33 |
Judge Schnoopy posted:I've got an odd powershell question that I can't seem to find an answer on. HKCU (HKEY_CURRENT_USER) only really exists for interactive logon sessions. When you remote to another machine, which user is "current"? If you want to enumerate Uninstall entries for local user accounts on another machine, your best bet is really to force the system user account service to load the profile. That should in turn cause the user hive to appear under HKEY_USERS (named after the account SID), where you might then be able to access it with remoting. As for forcing the user account service to load a profile, remotely, no idea.
|
|
# ¿ Feb 11, 2016 17:03 |
Are you sure it's the same user hive you're looking at with both commands? Really sure?
|
|
# ¿ Feb 11, 2016 17:18 |
Judge Schnoopy posted:... Try, on the remote (I think it must be done on the remote at least) to set up HKEY_USERS as a PSDrive and then check what profiles are available there: code:
Just keep in mind this will only get you user hives for profiles that are loaded on that machine right now. Usually means you'll see them for system accounts, service accounts, whatever account you're remoting in with, and then any users that have logged locally on to the machine after last boot. (Profiles of logged off users tend to stay loaded, at least for a while.)
|
|
# ¿ Feb 11, 2016 18:08 |
Alternative solution, perhaps: Use the Start-Job and Wait-Job cmdlets to create a job for each computer on your list, and have them run in parallel. Look up the about_Jobs help file to get some examples. If you go that way, you should probably not use "echo" or similar direct output, but rather have the jobs return one or more objects with the result, which you can then collate and process afterwards.
|
|
# ¿ Feb 22, 2016 15:21 |
Yes you can just do string interpolation:PHP code:
|
|
# ¿ Mar 21, 2016 20:24 |
Judge Schnoopy posted:So after writing a bunch of poo poo today I learned Forms cannot be passed to remote computers regardless of pssession or invoke command. Is best practice to create a secondary powershell or batch script and open that with invoke command? Or is there a better way to get a remote computer to display a message box with an input text box that writes to a file? You want the remote computer to display a message to and request input from whatever user is currently logged in on the console? I believe you will need to somehow launch a new process for the user under their login session for that to work. Otherwise you'll probably run into session 0 isolation. Assuming the account you use for remoting to the computer has local administrator, I think you can create a scheduled task that runs one time, as the currently logged in user, and then point it to some script file you've either copied to the machine, or on the network.
|
|
# ¿ Apr 28, 2016 06:16 |
The actual best solution I'd say, would be to use the Task Scheduler to define a task running interactive as the user and have it trigger on the appropriate event. That or PSEXEC are your primary choices for getting a program to run on an interactive desktop from remote. Or if you do prefer to search through the event log with PowerShell (remotely?) and then trigger it to run from that, use New-ScheduledTask to create one that runs as his user, when he is logged on, right away or a few minutes later.
|
|
# ¿ Apr 28, 2016 21:23 |
Does anyone know of a convenient way to interactively pick an OU (to create some object in) from AD, in a script? I can probably write something myself to make a basic menu kind of thing, but maybe something already exists.
|
|
# ¿ May 9, 2016 13:56 |
Ended up writing a simple CLI menu function:code:
|
|
# ¿ May 10, 2016 10:50 |
slightpirate posted:So good news is I've gotten my script to pull the testing OU into a CSV file, and I can edit it and push it back out to AD. That code is just assigning some variables. Are you actually passing that to your Get-ADUser command as well?
|
|
# ¿ May 23, 2016 08:13 |
If you want to remove users from particular groups when disabling them, I'd do something like what sloshmonger suggests, but maybe turn it around a bit.code:
There's really lots of ways to handle it.
|
|
# ¿ May 26, 2016 21:23 |
Get-ADUser is actually rather annoying re. error handling. When you use the form with -Identity (the default) it will throw an exception and not raise an error, when no object is found. Passing -ErrorAction does nothing about that. You have two options: 1. Catch the exception with try..catch 2. Search with -Filter instead code:
code:
|
|
# ¿ Jun 3, 2016 13:08 |
Dr. Arbitrary posted:
If you have PS 3.0 or newer, ForEach-Object can also straight take a member name to extract or call. Like this: $Userinput.Split(",") | ForEach-Object ToUpper
|
|
# ¿ Jun 7, 2016 20:12 |
slightpirate posted:I know this is going to sound goofy as all hell, but none of my scripts that were exporting to CSV are working now. The file gets created fine, but no headers or data get dumped and no errors are generated in ISE. Have you checked that the variables or pipelines you send to CSV actually contains any data? Also try piping your data to ConvertTo-CSV instead of Export-CSV, that will get you text output to view in the console instead.
|
|
# ¿ Jun 13, 2016 18:57 |
$AllADUsers is what? Nothing gets assigned to that in what you pasted.
|
|
# ¿ Jun 13, 2016 19:12 |
slightpirate posted:oh goddamnit. When I debug my PowerShell scripts, I usually do it by pasting each command in manually and examining the output. When something uses a variable I examine its current value, and if it looks wrong, double check how that value got there. Just being methodical like that finds 99% of all mistakes.
|
|
# ¿ Jun 13, 2016 19:54 |
sloshmonger posted:Is the destination share "C:"? Maybe it should be \\computer\c$\destinationpath I don't even think : is a valid character in share names.
|
|
# ¿ Jun 24, 2016 20:52 |
22 Eargesplitten posted:If I call a powershell script from within a powershell script, does the calling script keep going, or does it wait for the second to complete? I want to make mine keep going. If you just call it, it runs synchronously. If you want it to be asynchronous, you need to put it inside a Job. Get-Help Start-Job
|
|
# ¿ Jul 7, 2016 20:10 |
SeaborneClink posted:I mistakenly posted this in the Enterprise thread, and received a workable answer but am still hoping for something a little more... clean. The right way is the Known Folders API. https://msdn.microsoft.com/en-us/library/windows/desktop/bb776911.aspx On mobile right now so csn't type up an example. Edit: As far as I can tell, the types for this isn't defined in .NET proper, so you have to declare the related COM interfaces and more to make it work. nielsm fucked around with this message at 08:00 on Jul 8, 2016 |
|
# ¿ Jul 8, 2016 05:52 |
Here's a "PowerShell" way of calling that function to get a known folder path:code:
nielsm fucked around with this message at 09:25 on Jul 8, 2016 |
|
# ¿ Jul 8, 2016 09:18 |
More like this:code:
|
|
# ¿ Jul 11, 2016 16:55 |
Your code is an unreadable mess. Indent your poo poo properly, and stop making gigantic pipelines when writing scripts you intend to re-use. Gigantic long pipes mainly have use when experimenting on the commandline, and even then storing stuff into variables as intermediate steps makes it much easier to figure out where something might have gone wrong. Here's a possibly fixed version: code:
|
|
# ¿ Jul 13, 2016 18:16 |
Oh right, made a mistake editing it. The line should be: Remove-ADPrincipalGroupMembership -Identity $u.distinguishedname -MemberOf $_ -Confirm:$False
|
|
# ¿ Jul 13, 2016 18:34 |
Which part of your script is actually supposed to invoke the commands to run on the remote machine? That line starting a new Powershell.exe process just starts a process on your own machine. Do your target machines have WinRM enabled? If so, use Invoke-Command (with -AsJob flag) instead of Start-Job to just run PowerShell code directly on each target machine. If your target machine don't have WinRM enabled, or its execution policy doesn't allow remote scripting, you'll have to use some other trickery to get your code to run on it. Either the old psexec utility, or setting up a task scheduler job on it.
|
|
# ¿ Jul 14, 2016 19:20 |
You're missing my main point: Nothing in that code ever tells the remote computer to execute anything. You execute PowerShell.exe on your local computer, reading a script from a remote location. The script may be read from a remote location, but it still executes on your local computer. If you want to execute PowerShell code on a remote computer you need to use either Invoke-Command or Import-PSSession, or trickery with New-ScheduledTask or PSExec.
|
|
# ¿ Jul 14, 2016 20:39 |
Can you use classic Windows remote management with the target machines? E.g. open the Computer Management management console and connect to one of the machines, see its Device Manager etc.? If so, I would suggest something like this: InstallInstaller.ps1 (runs on your computer) code:
code:
Edit: Thinking about it, if you can't establish a CimSession like this, PSExec won't work either, since PSExec also depends on being able to connect to the service control manager of the remote computer to do its job. nielsm fucked around with this message at 19:55 on Jul 15, 2016 |
|
# ¿ Jul 15, 2016 19:15 |
I'd guess it has to do with escaping there. Try with a simpler command first, like Write-Host, make sure you can get that working. I think you must pass the -Command argument name to PowerShell.exe when giving it something to execute right away: psexec $computer powershell.exe -command { write-host test } There is also the option for -Base64EncodedCommand, which even has an example if you call Powershell.exe -Help. But really, it's probably safer to copy a script file or batch file to the remote and exec that, have the script figure out all its data on its own instead of messing around with escaping.
|
|
# ¿ Jul 16, 2016 06:45 |
That impersonation problem, can that perhaps be related to an issue I was having the other day? I was trying to run a GUI program as another user, using Start-Command -Credential (Get-Credential), loading the program from a network location given by full UNC path. I kept getting file not found errors, loading the program. Passing -LoadUserProfile made no difference. Doing the same thing with classic RunAs.ex works just fine.
|
|
# ¿ Jul 16, 2016 06:59 |
|
|
# ¿ Apr 29, 2024 01:24 |
Why are you trying to PSExec something any more complicated than the name of a batch file?
|
|
# ¿ Jul 18, 2016 19:22 |