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
Lum
Aug 13, 2003

Having PSRemoting fun again...

So I have a script that runs once a day, connects to a server on a different domain using Invoke-Command -Cred $Creds. Once it's connected it runs some SQL backups, passes the details back and then we copy those backups over SMB. It's done this way because inbound connections to your backup server are a bad idea in a post-cryptolocker world.

It's worked for months and then started failing with "The WSMan service could not launch a host process to process the given request". Couldn't find much on google but I checkes the TrustedHosts stuff, restarted the wsman service, added -SessionOption ( NewPSSesionOption -NoMachineProfile), even tried upgrading from PS 5.1 to PS 7.2

Eventually what cured it was a reboot.

Unfortunately that only lasted for 5 days and now the problem is back.

Any idea what it could be? I can't keep rebooting this server as it's not clustered or anything.

Adbot
ADBOT LOVES YOU

sloshmonger
Mar 21, 2013

Lum posted:

Having PSRemoting fun again...

So I have a script that runs once a day, connects to a server on a different domain using Invoke-Command -Cred $Creds. Once it's connected it runs some SQL backups, passes the details back and then we copy those backups over SMB. It's done this way because inbound connections to your backup server are a bad idea in a post-cryptolocker world.

It's worked for months and then started failing with "The WSMan service could not launch a host process to process the given request". Couldn't find much on google but I checkes the TrustedHosts stuff, restarted the wsman service, added -SessionOption ( NewPSSesionOption -NoMachineProfile), even tried upgrading from PS 5.1 to PS 7.2

Eventually what cured it was a reboot.

Unfortunately that only lasted for 5 days and now the problem is back.

Any idea what it could be? I can't keep rebooting this server as it's not clustered or anything.

How does it close out the connection? Maybe it's keeping ports open and you're seeing port exhaustion?

The Fool
Oct 16, 2003


Iirc there some potential problems with a max process count


E: check MaxProcessesPerShell and see if you’re hitting it

Lum
Aug 13, 2003

Maxprocesses per shell is set to 2.147 million.

The process is run as a background job, with the calling process using receive-job to pull status info. Is there something I need to do at the end of the job scriptblock to make it terminate properly?

Gerdalti
May 24, 2003

SPOON!
If you're using remote PS sessions, make sure you exit them, or they hang out.
https://docs.microsoft.com/en-us/powershell/scripting/learn/remoting/running-remote-commands

Lum
Aug 13, 2003

So I do

code:
Invoke-Command blah.local -asjob -scriptblock { 
  Do-stuff
  Exit-PSSession # add this
}

And that'll sort it?

Happiness Commando
Feb 1, 2002
$$ joy at gunpoint $$

Exit-PsSession exits out of interactive remote sessions - i.e. the result of Enter-PsSession. It doesn't terminate the session, that's what Remove-PsSession does. But it's not clear to me that open sessions are relevant here, since you're using Invoke-Command on a remote target. I have always assumed that invoke-command run against a remote host (edit: rather than through an open session) terminates its own ephemeral session.

How many executions do you get before it starts failing?

Edit: This might be informative

code:
PS C:\WINDOWS\system32> invoke-command -ScriptBlock{hostname}
Slim
PS C:\WINDOWS\system32> get-pssession
PS C:\WINDOWS\system32> invoke-command -ComputerName SOTINY -Credential $cred -ScriptBlock{hostname}
SOTINY
PS C:\WINDOWS\system32> get-pssession
PS C:\WINDOWS\system32>
code:
PS C:\WINDOWS\system32> get-pssession
PS C:\WINDOWS\system32> $sess = new-pssession -computername sotiny -credential $cred
PS C:\WINDOWS\system32> get-pssession

 Id Name            ComputerName    ComputerType    State         ConfigurationName     Availability
 -- ----            ------------    ------------    -----         -----------------     ------------
  5 WinRM5          sotiny          RemoteMachine   Opened        Microsoft.PowerShell     Available


PS C:\WINDOWS\system32> invoke-command -Session $sess -ScriptBlock {hostname}
SOTINY
PS C:\WINDOWS\system32> $sess | remove-pssession
PS C:\WINDOWS\system32> get-pssession
PS C:\WINDOWS\system32>
code:
PS C:\WINDOWS\system32> $sess = new-pssession -computername sotiny -credential $cred
PS C:\WINDOWS\system32> enter-pssession $sess
[sotiny]: PS C:\Users\Happiness Commando\Documents> hostname
SOTINY
[sotiny]: PS C:\Users\Happiness Commando\Documents> exit-pssession
PS C:\WINDOWS\system32> get-pssession

 Id Name            ComputerName    ComputerType    State         ConfigurationName     Availability
 -- ----            ------------    ------------    -----         -----------------     ------------
  6 WinRM6          sotiny          RemoteMachine   Opened        Microsoft.PowerShell     Available


PS C:\WINDOWS\system32> get-pssession |remove-pssession
PS C:\WINDOWS\system32>

Happiness Commando fucked around with this message at 19:50 on Nov 25, 2021

lol internet.
Sep 4, 2007
the internet makes you stupid
I made a script to do AD account management (ie. disable, move, clear fields.)

How can I go about creating logs? Ideally I want to have a log file I just write to, commands that got sent and if it was successful or not.

Also how would I send an email report saying which users were disabled. I am using a foreach loop to disable the accounts.

Toshimo
Aug 23, 2012

He's outta line...

But he's right!

lol internet. posted:

I made a script to do AD account management (ie. disable, move, clear fields.)

How can I go about creating logs? Ideally I want to have a log file I just write to, commands that got sent and if it was successful or not.

Also how would I send an email report saying which users were disabled. I am using a foreach loop to disable the accounts.

I'd start by throwing in Start-Transcript (https://ss64.com/ps/start-transcript.html) at the start of your script and see if that gets you where you need to be. You can invest a lot of time manually catching errors and logging actions, but is it worth it in the long run for this purpose?

Inspector_666
Oct 7, 2003

benny with the good hair
Send-Mailmessage is how you'd send the mail, too. Although apparently MS says you shouldn't use it, they also don't have a replacement so v0v


EDIT: Oh, I guess MailKit is the unofficial-but-still-MS-maintained solution now?

Inspector_666 fucked around with this message at 06:53 on Nov 27, 2021

Lum
Aug 13, 2003

Happiness Commando posted:

Exit-PsSession exits out of interactive remote sessions - i.e. the result of Enter-PsSession. It doesn't terminate the session, that's what Remove-PsSession does. But it's not clear to me that open sessions are relevant here, since you're using Invoke-Command on a remote target. I have always assumed that invoke-command run against a remote host (edit: rather than through an open session) terminates its own ephemeral session.

How many executions do you get before it starts failing?

Script worked fine for about 3 months, running once a day (although the remote server also gets rebooted once a month)

After getting the issue and exhausting troubleshooting options I ended up rebooting the remote server, and only got five executions before it failed again.

Happiness Commando
Feb 1, 2002
$$ joy at gunpoint $$

Have you confirmed that the necessary services on both target and source computers are still up even when it fails (i.e. whatever WinRM services, SQL services, whatever) or looked for interesting time correlated events in the event logs? 5 executions is weird AF, and even if remote Powershell happened over RPC, you wouldn't expect your RPC range to only be 5 ports wide.

Take a packet capture. Bonus points if you can get the capture of the nth execution that fails for the first time and the n-1th execution that immediately precedes the failure.

I'm very curious to find out what the resolution is,.

Lum
Aug 13, 2003

Happiness Commando posted:

Have you confirmed that the necessary services on both target and source computers are still up even when it fails (i.e. whatever WinRM services, SQL services, whatever) or looked for interesting time correlated events in the event logs? 5 executions is weird AF, and even if remote Powershell happened over RPC, you wouldn't expect your RPC range to only be 5 ports wide.

Take a packet capture. Bonus points if you can get the capture of the nth execution that fails for the first time and the n-1th execution that immediately precedes the failure.

I'm very curious to find out what the resolution is,.

WinRM service is up, and restarting it doesn't help.
SQL service isn't the issue as the old script worked (runs on the SQL server, pushes to the backup repository - we're trying to stop inbound SMB)

It's going to be hard to get a packet capture as it's an overnight script and the failure isn't predictable. This time around, since it was rebooted we've had 7 successful runs and it hasn't failed yet.

Inspector_666
Oct 7, 2003

benny with the good hair
Had to dick around with the Slack API today and looking at the flags available for Invoke-RestMethod in 7.2 got me to install it and it's much nicer even though the API doesn't support the cool pagination stuff.

Lum
Aug 13, 2003

Happiness Commando posted:

I'm very curious to find out what the resolution is,.

Well it hasn't come back. Not sure if co-incidence or if putting Exit-PSSession on the end of the script really did sort it.

If it did, I should probably wrap that poo poo up in a Try / Catch / Finally

Happiness Commando
Feb 1, 2002
$$ joy at gunpoint $$

Those are the worst/best problem resolutions

Toast Museum
Dec 3, 2005

30% Iron Chef
Here's something I discovered a few weeks ago but didn't have a use for until now. Normally, PowerShell requires using statements to go at the top of a script file, but it's possible to circumvent that rule:

PowerShell code:
# Top of file.
$Foo = Get-Foo

# Not top of file!
[scriptblock]::Create("using module C:\path\to\myModule.psd1").Invoke()

Get-ThingFromMyModule
My use case: I'm working on a compiled module, and I can't build the project while the module is loaded in a PowerShell process. With the syntax above, I can copy the module to a second location and then point to that path with the using statement.

Djimi
Jan 23, 2004

I like digital data
I have been tasked to fix a csv spreadsheet for our Finance dept, because the software that they use that generates reports is ... kinda dumb.

Here's a sample of a daily report of sales:

Order, Date, PayType, Transact, Deposit, Shipping, Handling, Taxes
10043, 2/4/22, CreditCard, 33.75, 0.00, 0.00, 0.00, 2.86
10044, 2/4/22, CreditCard, 15.66, 0.00, 0.00, 0.00, 1.33
10045, 2/4/22, CreditCard, 63.08, 0.00, 0.00, 0.00, 9.38
10045, 2/4/22, Cash, 60.00, 0.00, 0.00, 0.00, 9.38
10046, 2/4/22, CreditCard, 52.45, 0.00, 0.00, 0.00, 4.46
10047, 2/4/22, CreditCard, 30.00, 0.00, 5.00, 0.00, 4.60
10047, 2/4/22, Cash, 24.14, 0.00, 5.00, 0.00, 4.60
10048, 2/4/22, CreditCard, 50.92, 0.00, 0.00, 0.00, 4.32


So orders with two PayTypes (CreditCard and Cash usually), have two rows with the same order number.
10045 and 10047 are the examples in the above list.

And the dumb part of the program doubles the entry on the taxes every time and for shipping (and handling, and deposit—but so far those columns have not been populated with any numbers so far, but it may- I'm skipping for now).

Order:10045 has only the tax outputted twice: $9.38 and Order 10047 has Shipping: $5.00 and Taxes:$4.60 twice. I only need (want) the first occurence. So in 10045 the two transactions, 63.08 and 60 equal 123.08 and that is what I want summed. The actual price minus the tax is 113.70 - and I would like that in a column as well.

I would like to create a new column "Total" via Group Summing, but I don't know how I can choose to ignore or null the second occurrence (or third if they had a gift card, a credit card and cash or something). Do I have to iterate each row before to clean up the data, or does CSV magic in powershell have something to do that.

Here's what I'm hoping to use as the start (or finish), as I've done this before for grouping Department Codes sales:

code:
$csvmath = (Import-Csv $CsvFile |Group-Object Order,Date,Shipping,Taxes| `
Select-Object @{Name='Order';Expression={$_.Values[0]}},  `
              @{Name='Shipping' ;Expression={$_.Values[1]}}, `
              @{Name='Taxes' ;Expression={$_Values[2]}}, `
              @{Name='Total';Expression={($_.Group | Measure-Object Transact -Sum).Sum}}`
			  )
What's the best way to do this? Thank you.

The Fool
Oct 16, 2003


Of you absolutely must solve this problem yourself with code use Python+pandas instead of powershell

There might be a higher learning curve if you’ve never used it before but it is purpose built for solving these kinds of problems

Djimi
Jan 23, 2004

I like digital data

The Fool posted:

Of you absolutely must solve this problem yourself with code use Python+pandas instead of powershell

There might be a higher learning curve if you’ve never used it before but it is purpose built for solving these kinds of problems
I have used python a bit but not much. So this is a non-trivial PS to solve?

I was hoping that it would be a two step process (first remove >1 occurrence of tax, shipping, ... etc.) or it could be a single line/operation... but I'm not clever enough to figure it out. Much more comfortable for me to use Powershell. But I will look on Github and see what I can find. Thank you.

Submarine Sandpaper
May 27, 2007


Eh I wouldn't like to do this but it's not a hard solution.

Since you know your tax/shiping/handling is always multiplied by the occurance of the order you can just divide that out.

$math = $CSVfile | group order -NoElement

[...]


@{Name='Taxes' ;Expression={$_.Values[2] / $math[$math.values.IndexOf($_.Values[0])].Count}}, `


[...]

/e thinking about it more you probably will want to rebuild the data so maybe not as easy as just doing a calculation in the expression

Submarine Sandpaper fucked around with this message at 22:19 on Feb 6, 2022

Djimi
Jan 23, 2004

I like digital data

Submarine Sandpaper posted:


/e thinking about it more you probably will want to rebuild the data so maybe not as easy as just doing a calculation in the expression
Do you mean find duplicate orders (rows), export them separately and iterate through them and then work on the no dupe orders (unique order numbers) as another section of my script and then concatenate the two together?

I appreciate it if you could elaborate on the tax/shipping/handling comment about - those numbers *don't* add in to an already known total (money charged for an order, I left out that field. It's doubled as well, but it's only the sum of the TRANSACT column. It's not erroneously adding another shipping/tax amount.)

My thought would be that there was some elegant Powershell way that could do this, in less steps, or that I wasn't seeing the problem correctly. Well I know I'm seeing the math/finance part. It's not something I've worked on before.

Thanks for your help.

Toast Museum
Dec 3, 2005

30% Iron Chef
I'll come back when I've given it more thought and have time for a longer post, but my initial inclination is to break out each payment type's amount to a separate property (CashAmount, CardAmount, etc).

Mario
Oct 29, 2006
It's-a-me!
Taking advantage of the taxes value always being duplicated, you can remove it from the grouping and instead take an aggregation on it (min, max, avg) to get the desired result:

PowerShell code:
$csvmath = (Import-Csv $CsvFile |Group-Object Order,Date| `
Select-Object @{Name='Order';Expression={$_.Values[0]}},  `
              @{Name='Shipping' ;Expression={$_.Values[1]}}, `
              @{Name='Taxes';Expression={($_.Group | Measure-Object Taxes -Minimum).Minimum}}, `
              @{Name='Total';Expression={($_.Group | Measure-Object Transact -Sum).Sum}}, `
              @{Name='TotalLessTaxes';Expression={($_.Group | Measure-Object Transact -Sum).Sum - ($_.Group | Measure-Object Taxes -Minimum).Minimum}} `
              )
pre:
Order Shipping Taxes  Total TotalLessTaxes
----- -------- -----  ----- --------------
10043 2/4/22    2.86  33.75          30.89
10044 2/4/22    1.33  15.66          14.33
10045 2/4/22    9.38 123.08          113.7
10046 2/4/22    4.46  52.45          47.99
10047 2/4/22     4.6  54.14          49.54
10048 2/4/22    4.32  50.92           46.6

Toast Museum
Dec 3, 2005

30% Iron Chef
Re-reading the problem more carefully and not on my phone, it looks like I was assuming more data needs to be preserved than actually does. If we don't care about dates or payment types, here's how I went about it. Maybe defining the class in C# is cheating a little; but it's easier than browbeating custom getter/setter behavior into a PowerShell class.

Basically, my approach is to stick the CSV data in a dictionary keyed to order number. That way, as we go down the CSV, when there are multiple lines with one order number, we can add Transact to the entry's current total and not care if the other fields get overwritten with the values they already have.

PowerShell code:
using namespace System.Collections.Generic
$TypeDef = @"
using System.Collections.Generic;
public class Purchase
{
    public int Order {get; set;}
    public double Shipping {get; set;}
    public double Taxes {get; set;}
    public double Subtotal => Total - Shipping - Taxes;
    public double Total {get; set;}
}
"@
Add-Type -TypeDefinition $TypeDef

$Purchases = [Dictionary[[int],[Purchase]]]::new()

Import-Csv -Path $Path | ForEach-Object {
    $order = $_.order
    if ($null -eq $Purchases[$order])
    {
        $Purchases[$order] = [Purchase]::new()
    }
    $Purchases[$order].Order = $order
    $Purchases[$order].Shipping = $_.Shipping
    $Purchases[$order].Taxes = $_.Taxes
    $Purchases[$order].Total += $_.Transact
}
Edit: gave the Purchase class a constructor with parameters for the properties that would be duplicated on multi-row orders, avoiding three unnecessary assignment operations for each row beyond an order's first.

PowerShell code:
using namespace System.Collections.Generic
$TypeDef = @"
using System.Collections.Generic;
public class Purchase
{
    public int Order {get; set;}
    public double Shipping {get; set;}
    public double Taxes {get; set;}
    public double Subtotal => Total - Shipping - Taxes;
    public double Total {get; set;}

    public Purchase (int order, double shipping, double taxes)
    {
        Order = order;
        Shipping = shipping;
        Taxes = taxes;
    }
}
"@
Add-Type -TypeDefinition $TypeDef

$Purchases = [Dictionary[[int],[Purchase]]]::new()

Import-Csv -Path $Path | ForEach-Object {
    if ($null -eq $Purchases[$_.Order])
    {
        $Purchases[$_.Order] = [Purchase]::new($_.Order, $_.Shipping, $_.Taxes)
    }
    $Purchases[$_.Order].Total += $_.Transact
}

Toast Museum fucked around with this message at 23:57 on Feb 9, 2022

Djimi
Jan 23, 2004

I like digital data

Mario posted:

Taking advantage of the taxes value always being duplicated, you can remove it from the grouping and instead take an aggregation on it (min, max, avg) to get the desired result:
That’s a cool trick to use measure-object minimum property, and I may be able to employ that. Thank you.

Toast Museum posted:

Re-reading the problem more carefully and not on my phone, it looks like I was assuming more data needs to be preserved than actually does. If we don't care about dates or payment types, here's how I went about it. Maybe defining the class in C# is cheating a little; but it's easier than browbeating custom getter/setter behavior into a PowerShell class.
I was originally going to the report reconciliation once a week, but chief bean counter said he wants to run it each day, for the prior day, so the date will be the same for all rows processed. Payment type is just handy to see, but also won't be included in the transaction amount.

Toast Museum posted:

Basically, my approach is to stick the CSV data in a dictionary keyed to order number. That way, as we go down the CSV, when there are multiple lines with one order number, we can add Transact to the entry's current total and not care if the other fields get overwritten with the values they already have.

Toast Museum posted:

Classy Code…
I’m sorry for the delay in writing back. I am still waiting on the final GL output that Finance wants, and I am also waiting for getting the daily file via scp or an API (that I don’t know if it exists yet… waiting on a reply email).

But this is super helpful and I will let you know how it goes. Extremely grateful. :tipshat:

Soylent Majority
Jul 13, 2020

Dune 2: Chicks At The Same Time
I've fussed with powershell years ago but haven't really dug in on anything, and I think I've found a good way to ease myself into things, I'm hoping for some help in guiding me through how I'd go about doing the following since learning excel janitoring is less useful to me long term vs powershell:

Shareddrives.xlsx has a stupid amount of data about various fileshares, listing owner1, owner2, size, etc
Users.xlsx has a bunch of info about users I take care of - name, employeeID, email address etc.

I want to extract the information in Shareddrives.xlsx where owner1 and/or owner2 is one of the people in users.xlsx and output it in a manner that lets me see that USER1 is an owner for shareX and shareY, USER2 is owner of shareQ, etc.

This seems like it's a simple enough problem to address, but being pretty green to this poo poo I'm not sure how to actually approach it.

Happiness Commando
Feb 1, 2002
$$ joy at gunpoint $$

Sounds like you want to do SQL join-like operation:

code:
SELECT * FROM Shareddrives.xlsx INNER JOIN Users.xlsx ON Shareddrives.xlsx.owner1 = Users.xlsx.username
I'd probably use Join-Object after first ingesting the Excel files as CSVs using Import-CSV

Edit: Oh, hmm, IDK how this pattern would work if you have to look at owner1 or owner2. What about something like this? First you populate your variables, or in the case of the output hashtable, initialize it and leave it empty. Then iterate through all the lines of the users file. For each row of the users file, iterate through all the lines of the shared drives file. If the username matches either of the owners, store it in a temp variable and then write it to the output hashtable. When you've gone through every line, dump the output to a csv. This is super hacky (using the % alias of Foreach-Object is bad practice, using Foreach-Object isn't performant, there's probably a more elegant way) but I think it will work as described.
code:
$users = import-csv users.csv
$shareddrives = import-csv shareddrives.csv
$output = @{}

$users | % {
    $username = $_.username
    $shareddrives | % {
        if ($username -eq $_.owner1){
            $owner = $_.owner1
         } 
         if ($username -eq $_.owner2){
            $owner = $_.owner2
         }
         $output.add($_.sharepath, $owner)
    }
     
}
$output | export-csv -path c:\shareddriveowners.csv
"how to approach it" is either breaking down the problem into atomic operations or pattern-matching for a solution you've already found. In this case, I've approached it as:

Import the .xlsx files so you can do stuff with them
Match the username with the owner field
Dump the output somewhere

and "Match the username with the owner field" is approached as

Store the username somewhere
Compare the username to each of the owner fields
If it matches, add it to my list to output at the end
If it doesn't match, keep looking

Happiness Commando fucked around with this message at 05:31 on Mar 2, 2022

Soylent Majority
Jul 13, 2020

Dune 2: Chicks At The Same Time
This is super helpful, thank you - imma play with this a bit and see if I can't make it cooperate.

Toast Museum
Dec 3, 2005

30% Iron Chef

Soylent Majority posted:

I've fussed with powershell years ago but haven't really dug in on anything, and I think I've found a good way to ease myself into things, I'm hoping for some help in guiding me through how I'd go about doing the following since learning excel janitoring is less useful to me long term vs powershell:

Shareddrives.xlsx has a stupid amount of data about various fileshares, listing owner1, owner2, size, etc
Users.xlsx has a bunch of info about users I take care of - name, employeeID, email address etc.

I want to extract the information in Shareddrives.xlsx where owner1 and/or owner2 is one of the people in users.xlsx and output it in a manner that lets me see that USER1 is an owner for shareX and shareY, USER2 is owner of shareQ, etc.

This seems like it's a simple enough problem to address, but being pretty green to this poo poo I'm not sure how to actually approach it.

It sounds like you want to incorporate the information from SharedDrives into Users; is that right? Can you provide an example of how each spreadsheet is structured? Assuming that, for a given drive, each owner is in a separate cell in SharedDrives, I'd approach it like this:

PowerShell code:
$Users = Import-Csv -Path "Path\To\Users.csv"
$SharedDrives = Import-Csv -Path "Path\To\SharedDrives.csv"

foreach ($Drive in $SharedDrives)
{
    Add-Member -InputObject $Drive -MemberType NoteProperty -TypeName [string[]] -Name "Owners" -Value $Drive.Owner1, $Drive.Owner2, $Drive.Owner3 # etc.
}

foreach ($User in $Users)
{
    $OwnedDrives = $SharedDrives | Where-Object Owners -Contains $User.Username | Select-Object -ExpandProperty DriveName
    Add-Member -InputObject $User -MemberType NoteProperty -TypeName [string[]] -Name "OwnedDrives" -Value $OwnedDrives
}

Export-Csv -InputObject $Users -Path "Path\To\Users.csv"
Basically: collect all the owners for each drive into a single Owners property. Then, for each user, make a property containing the name of each drive whose Owners property contains that user's username.

Edit: thought of an alternative version of that first foreach block that doesn't require you to explicitly name each Owner property.
PowerShell code:
foreach ($Drive in $SharedDrives)
{
    $Owners = $Drive.PSObject.Properties | Where-Object {$_.Name -match '^Owner[0-9]+$'} | Select-Object -ExpandProperty Value
    Add-Member -InputObject $Drive -MemberType NoteProperty -TypeName [string[]] -Name "Owners" -Value $Owners
}

Toast Museum fucked around with this message at 22:54 on Mar 2, 2022

Happiness Commando
Feb 1, 2002
$$ joy at gunpoint $$

Ooh that's slick

incoherent
Apr 24, 2004

01010100011010000111001
00110100101101100011011
000110010101110010
Hey all, trying to write baby first parameter based script and i'm sure I'm in over my head and it's probably the simplest thing to write ever, but i can't link all the parts together.

The task: To take a parameter given to it from the command line (for example: -dept "shipping") and two different variables (which I'm reading should be an "arrays") list to the command i'm running.

I need to define that "shipping" is $dept and $deptFile and fill in where entered.

(Yes, yes my name is my name. I'm sure there is a better way of articulating this!)

Happiness Commando
Feb 1, 2002
$$ joy at gunpoint $$

incoherent posted:

Hey all, trying to write baby first parameter based script and i'm sure I'm in over my head and it's probably the simplest thing to write ever, but i can't link all the parts together.

The task: To take a parameter given to it from the command line (for example: -dept "shipping") and two different variables (which I'm reading should be an "arrays") list to the command i'm running.

I need to define that "shipping" is $dept and $deptFile and fill in where entered.

(Yes, yes my name is my name. I'm sure there is a better way of articulating this!)

I dont understand what you're asking for when you say "two different variables (which I'm reading should be an "arrays") list to the command i'm running."

At the simplest level, you define a parameter with param ($ParamName). So if you want to do -dept "shipping", you would put at the top of your script param ($dept) and then run it as .\myscript.ps1 -dept "shipping". And then inside the script, the variable $dept stores the string "shipping".

If you want to get more complicated, you can cast the parameters as types (switch, boolean, whatever), make them mandatory or not, set an order, etc. But at their most basic, you just throw them in a variable and call the script using that variable as a flag.

Happiness Commando fucked around with this message at 19:28 on Mar 11, 2022

incoherent
Apr 24, 2004

01010100011010000111001
00110100101101100011011
000110010101110010

Happiness Commando posted:

I dont understand

Let me try another way of explaining.

.\foo.ps1 -dept "shipping" needs to refer two variables, $dept and $deptfile. $dept is a list of departments (shipping, legal, printshop) and $deptfile (c:\folders\File01.txt, C:\folders\file02.txt, C:\folders\file.03.txt) is a list of items. Both will be used in a command.

in the script they should be passed like so: C:\app\app.exe -$Dept -$depfile. I suspect it output would be C:\app\app.exe -$dept[0] $deptfile[0] but how do I explain shipping = $dept[0] and $deptfile[0] to powershell.

I'd like to do this with one parameter, but I will settle for two.

Nth Doctor
Sep 7, 2010

Darkrai used Dream Eater!
It's super effective!


incoherent posted:

Let me try another way of explaining.

.\foo.ps1 -dept "shipping" needs to refer two variables, $dept and $deptfile. $dept is a list of departments (shipping, legal, printshop) and $deptfile (c:\folders\File01.txt, C:\folders\file02.txt, C:\folders\file.03.txt) is a list of items. Both will be used in a command.

in the script they should be passed like so: C:\app\app.exe -$Dept -$depfile. I suspect it output would be C:\app\app.exe -$dept[0] $deptfile[0] but how do I explain shipping = $dept[0] and $deptfile[0] to powershell.

I'd like to do this with one parameter, but I will settle for two.

I'm worried I've lost the thread here, but from your example I see a few things:
1. You want to pass one or more values into foo.ps1. Cool, we're all here for this.
2. The value or values passed in to foo.ps1 are used as parameter for a call to app.exe within foo.ps1
3. app.exe doesn't use parameter naming for the command line switches.

Are you saying that app.exe has a different CLI parameter for each department? What does that mean in terms of the behavior of app.exe?
app.exe -Shipping -C:\path\to\shipping\files\1.txt.exe.pdf does one thing but
app.exe -legal -C:\path\to\legal\files\Two_Final_2_UseThisOne.docx does something completely different?

Toast Museum
Dec 3, 2005

30% Iron Chef

incoherent posted:

Let me try another way of explaining.

.\foo.ps1 -dept "shipping" needs to refer two variables, $dept and $deptfile. $dept is a list of departments (shipping, legal, printshop) and $deptfile (c:\folders\File01.txt, C:\folders\file02.txt, C:\folders\file.03.txt) is a list of items. Both will be used in a command.

in the script they should be passed like so: C:\app\app.exe -$Dept -$depfile. I suspect it output would be C:\app\app.exe -$dept[0] $deptfile[0] but how do I explain shipping = $dept[0] and $deptfile[0] to powershell.

I'd like to do this with one parameter, but I will settle for two.

If I understand correctly, foo.ps1 invokes app.exe at some point, and app.exe takes -Dept and -DeptFile as parameters. foo.ps1 contains two collections, $Dept and $DeptFile, and one value from each of these collections should be passed to app.exe as parameters. Therefore, foo.ps1 needs one or more parameters to tell it which values to select from those two collections. Have I got that right?

Does a given department always use the same file, or does each value of Dept have multiple possible values of DeptFile?

incoherent
Apr 24, 2004

01010100011010000111001
00110100101101100011011
000110010101110010

Nth Doctor posted:

I'm worried I've lost the thread here, but from your example I see a few things:
1. You want to pass one or more values into foo.ps1. Cool, we're all here for this.
2. The value or values passed in to foo.ps1 are used as parameter for a call to app.exe within foo.ps1
3. app.exe doesn't use parameter naming for the command line switches.

Are you saying that app.exe has a different CLI parameter for each department? What does that mean in terms of the behavior of app.exe?
app.exe -Shipping -C:\path\to\shipping\files\1.txt.exe.pdf does one thing but
app.exe -legal -C:\path\to\legal\files\Two_Final_2_UseThisOne.docx does something completely different?

i'm sure there is a proper way of going about this, so i'll just show my desire result.

using the foo.ps1 -shipping would effectively run C:\app\app.exe -shipping -C:\folder\file01.txt. If i ran a -legal parameter it would run c:\app\app.exe -legal -c:\folder\file02.exe.

There would be a list of dept and a list of the respective files to run.

Toast Museum posted:

If I understand correctly, foo.ps1 invokes app.exe at some point, and app.exe takes -Dept and -DeptFile as parameters. foo.ps1 contains two collections, $Dept and $DeptFile, and one value from each of these collections should be passed to app.exe as parameters. Therefore, foo.ps1 needs one or more parameters to tell it which values to select from those two collections. Have I got that right?

Does a given department always use the same file, or does each value of Dept have multiple possible values of DeptFile?

yes there we go! one dept would have one file. however, I'd like to get it done in one parameter because they're fixed.

The Fool
Oct 16, 2003


bare bones phone posting:

code:
param($department)

$fileLookup = @{
  shipping = "file01"
  legal = "file02"
}

& app.exe -dept $department -file $fileLookup[$department]

incoherent
Apr 24, 2004

01010100011010000111001
00110100101101100011011
000110010101110010

The Fool posted:

bare bones phone posting:

code:
param($department)

$fileLookup = @{
  shipping = "file01"
  legal = "file02"
}

& app.exe -dept $department -file $fileLookup[$department]


Thank you for this! I didn't read anywhere I could do shipping = "file01" in array.

Adbot
ADBOT LOVES YOU

The Fool
Oct 16, 2003


it's called a hashtable

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