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
anthonypants
May 6, 2007

by Nyc_Tattoo
Dinosaur Gum

Judge Schnoopy posted:

Can somebody here shed some light on the proper way to do this?

I have a collection of custom objects that have different properties. I'm using a single loop to say if target matches object.propertyA, but if propertyA doesn't exist, check if target matches object.propertyB. To accomplish this I'm doing a try / catch, but since I expect the error a lot, catch returns $null.



For B, I expect the first if statement to throw an error complaining that property B.a doesn't exist. I want this error to be silent and for the script to move on.

I'm guessing I shouldn't be doing a try catch here but can't come up with the right answer to use instead.

Suggestions?
code:
$collection = @[{name = A, a = a},{name = B, b = b}]
Foreach ($thing in $collection) {
    If ($thing.a -match 'a') {
        return $true
    } elseif ($thing.b -match 'b') {
        return $true
    } else {
        $null
    }
}

Adbot
ADBOT LOVES YOU

mystes
May 31, 2006

Judge Schnoopy posted:

Can somebody here shed some light on the proper way to do this?

I have a collection of custom objects that have different properties. I'm using a single loop to say if target matches object.propertyA, but if propertyA doesn't exist, check if target matches object.propertyB. To accomplish this I'm doing a try / catch, but since I expect the error a lot, catch returns $null.

$collection = @[{name = A, a = a},{name = B, b = b}]
Foreach ($thing in $collection) {
Try{
If ($thing.a -match 'a'){return $true}
}
Catch {$null}
Try {
If ($thing.b -match 'b'){return $true}
}
Catch {$null}
}

For B, I expect the first if statement to throw an error complaining that property B.a doesn't exist. I want this error to be silent and for the script to move on.

I'm guessing I shouldn't be doing a try catch here but can't come up with the right answer to use instead.

Suggestions?
Maybe I'm misunderstanding something because I'm not that knowledgeable about powershell, but first of all "@[{name = A, a = a},{name = B, b = b}]" really what you actually want to write here? Is this even valid powershell code? Are you trying to do
code:
$collection = (@{name = 'A'; a = 'a'},@{name = 'B'; b = 'b'})
If so you can do
code:
if ($item.ContainsKey('a')) {
$item['a'] #or $item.a
}


Edit: also these aren't pscustomobjects, they're just hashtables.

Edit 2: Ignoring the syntax and assuming you do have a list of pscustomobjects, you can use "$item | Get-Member -MemberType NoteProperty" to see what properties it has
code:
if (($item | Get-Member -MemberType NoteProperty | ? {$_.name -eq "a"} | select -First 1) -ne $null) {
	if ($item.a -eq 'a') {
		return $true
	}	
}

mystes fucked around with this message at 02:04 on Oct 12, 2018

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord
Even with all that PowerShell won't throw an exception if the value of your object property is null, so performing an evaluation of the value (real or non-existent) is fine as-is.

Simply
code:
ForEach ($Thing in $Collection) {
	If ($Thing.a) { If ($Thing.a -Match "a") { Return $True } }
	If ($Thing.b) { If ($Thing.b -Match "b") { Return $True } }
	Return $Null
}
will work just fine. Note that it's going to hit the first match and ditch the rest of your objects, so if you're looking to build some type of full checklist you should instead either put the object and the result in a hash table or build a list of some sort.

Something PowerShell does that a lot of other languages don't is allow you to evaluate the existence of value from a variable in an If statement, so you can key conditions off a specific variable without typing as much (i.e. "variable.value == null", etc.). It's handy and for your purpose if you want to note whether a property exists and add other conditional behaviors on that it's pretty easy to do.

mystes
May 31, 2006

PierreTheMime posted:

Even with all that PowerShell won't throw an exception if the value of your object property is null, so performing an evaluation of the value (real or non-existent) is fine as-is.

Simply
code:
ForEach ($Thing in $Collection) {
	If ($Thing.a) { If ($Thing.a -Match "a") { Return $True } }
	If ($Thing.b) { If ($Thing.b -Match "b") { Return $True } }
	Return $Null
}
will work just fine. Note that it's going to hit the first match and ditch the rest of your objects, so if you're looking to build some type of full checklist you should instead either put the object and the result in a hash table or build a list of some sort.

Something PowerShell does that a lot of other languages don't is allow you to evaluate the existence of value from a variable in an If statement, so you can key conditions off a specific variable without typing as much (i.e. "variable.value == null", etc.). It's handy and for your purpose if you want to note whether a property exists and add other conditional behaviors on that it's pretty easy to do.
I recommend using strict mode (in which case this does produce an error) and writing the tiny amount of extra code to make sure stuff actually exists. Writing powershell code with strict mode off is a recipe for disaster.

Judge Schnoopy
Nov 2, 2005

dont even TRY it, pal

mystes posted:

I recommend using strict mode (in which case this does produce an error) and writing the tiny amount of extra code to make sure stuff actually exists. Writing powershell code with strict mode off is a recipe for disaster.

We use strict mode and that's where the trouble lies. I can't even do a if($thing.a) to check, because B will throw an exception for not having property a.

I was phone-posting so no the syntax is not correct, I was just trying to convey the difference in properties and how I'm trying to compare them.

I also found out that throwing $null is idiotic as gently caress because guess what happens when the last condition throws an exception? That's right, my collection of matches gets wiped away by the throw{$null}. Duh.

Get-member sounds like it's going to care of my problem, thanks!

e; AHA! I'm either smarter than I know or luckier than I am smart. At some point I added a 'type' property to each custom object in case I needed that info later. And now I can just do If($thing.type -eq 'ThingWithA') and If($Thing.type -eq 'ThingWithB') instead.

Judge Schnoopy fucked around with this message at 03:10 on Oct 12, 2018

Zaepho
Oct 31, 2013

Judge Schnoopy posted:

Can somebody here shed some light on the proper way to do this?

I have a collection of custom objects that have different properties. I'm using a single loop to say if target matches object.propertyA, but if propertyA doesn't exist, check if target matches object.propertyB. To accomplish this I'm doing a try / catch, but since I expect the error a lot, catch returns $null.

$collection = @[{name = A, a = a},{name = B, b = b}]
Foreach ($thing in $collection) {
Try{
If ($thing.a -match 'a'){return $true}
}
Catch {$null}
Try {
If ($thing.b -match 'b'){return $true}
}
Catch {$null}
}

For B, I expect the first if statement to throw an error complaining that property B.a doesn't exist. I want this error to be silent and for the script to move on.

I'm guessing I shouldn't be doing a try catch here but can't come up with the right answer to use instead.

Suggestions?
'a' -in $thing.keys maybe?

Pile Of Garbage
May 28, 2007



Judge Schnoopy posted:

We use strict mode and that's where the trouble lies. I can't even do a if($thing.a) to check, because B will throw an exception for not having property a.

I was phone-posting so no the syntax is not correct, I was just trying to convey the difference in properties and how I'm trying to compare them.

I also found out that throwing $null is idiotic as gently caress because guess what happens when the last condition throws an exception? That's right, my collection of matches gets wiped away by the throw{$null}. Duh.

Get-member sounds like it's going to care of my problem, thanks!

e; AHA! I'm either smarter than I know or luckier than I am smart. At some point I added a 'type' property to each custom object in case I needed that info later. And now I can just do If($thing.type -eq 'ThingWithA') and If($Thing.type -eq 'ThingWithB') instead.

You'll avoid a lot of grief if you make sure that arrays of objects contain objects of the same type and with the same members. If you need to combine properties from multiple sources then create new custom objects with the required properties. I find the easiest way is to just use New-Object and then Add-Member with the NotePropertyMembers parameter which accepts a hashtable of keys/values. Also Select-Object is really powerful and allows you to transform objects on the fly Name/Expression pairs. For example (Kind of lame but only one I could think of on the spot):

code:
$Properties = @(
    'FullName'
    @{
        Name = 'FullNameLower'
        Expression = { $_.FullName.ToLower() }
    }
)

Get-ChildItem | Select-Object -Property $Properties
Select-Object is really underutilised IMO.

Judge Schnoopy
Nov 2, 2005

dont even TRY it, pal
I ended up refactoring my objects to have the same core properties, and use the same view XML. Now I can treat them all the same instead of making three separate cases. Each 'type' just has extraneous properties that are useful, but not required by the script for anything.

Now I need to figure out how to retain order on items found in a JSON. Order matters, but my output seems to throw objects from all over the place. Nothing in the JSON object indicates order, which I guess is my downfall.

mystes
May 31, 2006

Judge Schnoopy posted:

Now I need to figure out how to retain order on items found in a JSON. Order matters, but my output seems to throw objects from all over the place. Nothing in the JSON object indicates order, which I guess is my downfall.
If you need to preserve the order of the keys I think you are going to need to use an OrderedDictionary rather than a PSCustomObject but I'm not sure JSON is really supposed to work that way.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug
Is there a way other than by twiddling around in the hosts file that I can add a DNS entry to a single Windows PC?

(I basically need to add a DNS entry for a PaaS service, deploy to PaaS service, then remove the DNS entry -- boring red tape-y issues prevent this from being handled sanely for the time being)

Judge Schnoopy
Nov 2, 2005

dont even TRY it, pal

mystes posted:

If you need to preserve the order of the keys I think you are going to need to use an OrderedDictionary rather than a PSCustomObject but I'm not sure JSON is really supposed to work that way.

This project is super convoluted at this point, but the JSON isn't a custom object. The JSON is a bunch of nested hashtables in arrays in hashtables in arrays, from a completely separate source. My tool is trying to make sense of that JSON data by searching, building custom objects, and displaying nicely.

The JSON Array is in the correct order, but my searching doesn't appear to keep that order when finding results. I'm not sure what step is jumbling the results. I think I'm going to just build in an 'Order' tag when I'm pulling from the primary source and building the JSON. Then I can just look at that property instead of making sure my search isn't loving up.

anthonypants
May 6, 2007

by Nyc_Tattoo
Dinosaur Gum

New Yorp New Yorp posted:

Is there a way other than by twiddling around in the hosts file that I can add a DNS entry to a single Windows PC?

(I basically need to add a DNS entry for a PaaS service, deploy to PaaS service, then remove the DNS entry -- boring red tape-y issues prevent this from being handled sanely for the time being)
You either put it in the hosts file or you put it on a DNS resolver or you use the IP address instead of the hostname.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

anthonypants posted:

You either put it in the hosts file or you put it on a DNS resolver or you use the IP address instead of the hostname.

That's what I thought. Can't use the IP directly, so I guess I'll either deal with it or build something to safely manipulate entries in the hosts file. Bummer.

Pile Of Garbage
May 28, 2007



Judge Schnoopy posted:

Now I need to figure out how to retain order on items found in a JSON. Order matters, but my output seems to throw objects from all over the place. Nothing in the JSON object indicates order, which I guess is my downfall.

Why does order matter? Order should never matter for any key/value pair object be it dict, hashtable or JSON. If you can elaborate on why order somehow matters then maybe we can fix that issue instead.

Also the thing I mentioned before about Select-Object? Well the array of names you pass to the Properties parameter are parsed in that exact order so you can actually re-order properties. For example:

code:
PS C:\> Get-ChildItem

    Directory: C:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       15/09/2018   3:33 PM                PerfLogs
d-r---        7/10/2018   1:42 PM                Program Files
d-r---        4/10/2018   4:03 AM                Program Files (x86)
d-r---        3/10/2018   7:39 PM                Users
d-----       12/10/2018   7:36 PM                Windows
-a----       25/05/2017   7:04 PM          63125 HIDLogFile.txt


PS C:\> Get-ChildItem | Select-Object -Property Name,Length,LastWriteTime,Mode

Name                Length LastWriteTime         Mode
----                ------ -------------         ----
PerfLogs                   15/09/2018 3:33:50 PM d-----
Program Files              7/10/2018 1:42:18 PM  d-r---
Program Files (x86)        4/10/2018 4:03:32 AM  d-r---
Users                      3/10/2018 7:39:32 PM  d-r---
Windows                    12/10/2018 7:36:07 PM d-----
HIDLogFile.txt      63125  25/05/2017 7:04:39 PM -a----

New Yorp New Yorp posted:

Is there a way other than by twiddling around in the hosts file that I can add a DNS entry to a single Windows PC?

(I basically need to add a DNS entry for a PaaS service, deploy to PaaS service, then remove the DNS entry -- boring red tape-y issues prevent this from being handled sanely for the time being)

Nope. Hosts file is the only local fall back for name resolution on Windows, unless you go comedy-option and spin up a resolver on the client itself to temporarily resolve queries. Tell whoever is in charge of your local resolvers to stop being a dick.

Judge Schnoopy
Nov 2, 2005

dont even TRY it, pal

Pile Of Garbage posted:

Why does order matter? Order should never matter for any key/value pair object be it dict, hashtable or JSON. If you can elaborate on why order somehow matters then maybe we can fix that issue instead.


The source json is firewall rules so order most definitely matters. The hashtables are set into arrays in order in the json.

Either way, my extraction tool is now tracking 'order number' so I can sort and resort and put back to normal whenever I want.

Submarine Sandpaper
May 27, 2007


Getting some odd stuff with SMA and hopefully someone has encountered this before.

Briefly, I'm creating a ticket, applying a template to overwrite it, then pulling the object. Later on I'll be using the object to apply user relationships to it and description changes. What's annoying is that if I launch this as a job in SMA it works, if I run it through the ISE console with the SMA ISE add-on it works, but when I call this with another runbook it errors out with, "A parameter cannot be found that matches parameter name 'eq'. (A parameter cannot be found that matches parameter name 'eq'.)"
It's breaking at: $SRProjection = Get-SCSMObjectProjection -ProjectionName $SRTypeProjection.Name -filter “ID -eq $SRID” @connection
It seems to want a GUID for this filter but when running the get-scsmobjectprojections and selecting any of those objects, none have ID in GUID format :(((((
code:
#properties mandatory are in there but will be overwritten by the template, ID is for callback. 
    $SRProperties = @{"Title" = "Placeholder";     #Required 
                    "Description" = "Placeholder"; #Required 
                    "Priority" = $SRPriority;      #Required  
                    "Urgency" = $SRUrgency;        #Required 
                    "ID" = "SR{0}"
                    }
    #Creates generic SR
    $NewSR = New-SCSMObject -Class $SRClass -PropertyHashtable $SRProperties -PassThru @connection
    
    #Can use __InternalID for GUID if needed
    $SRID = $NewSR.ID 
    
    #Gets service request projection
    $SRTypeProjection = Get-SCSMTypeProjection -name System.WorkItem.ServiceRequest.FormProjection$ @connection
    
    #Uses ID to pull created ticket as projection.
    $SRProjection = Get-SCSMObjectProjection -ProjectionName $SRTypeProjection.Name -filter “ID -eq $SRID” @connection    
    
    #pulls template and applies to ticket
    Set-SCSMObjectTemplate -Projection $SRProjection -Template $SRTemplate @connection
    Write-Output "$TemplateName applied to Service Request $SRID"

    #Pulls ticket as object to apply relationships and changes later
    $SRObject = get-scsmobject -Class $SRClass -filter "ID -eq $SRID" @connection
Driving me crazy, glad its friday.

Submarine Sandpaper fucked around with this message at 21:18 on Oct 26, 2018

PBS
Sep 21, 2015
What makes you think it wants a GUID?

Didn't know you could just put your filter values in quotes, I've always used curly braces and parentheses.

Get-ADUser -Filter {(Title -eq 'CEO')}

Submarine Sandpaper
May 27, 2007


When I purposefully break it by putting an invalid ID and run it manually the exception is asking for a GUID.

/E without writing the property ID, the ID that's generated for the exception just lacks SR so it's not even a guid.

Submarine Sandpaper fucked around with this message at 14:46 on Oct 27, 2018

PBS
Sep 21, 2015

Submarine Sandpaper posted:

When I purposefully break it by putting an invalid ID and run it manually the exception is asking for a GUID.

/E without writing the property ID, the ID that's generated for the exception just lacks SR so it's not even a guid.

From the error it sounds like it doesn't like your filter.

""A parameter cannot be found that matches parameter name 'eq'. (A parameter cannot be found that matches parameter name 'eq'.)""

Can you try another filter format? Or provide the full body of relevant errors? $error[0] | select *

Submarine Sandpaper
May 27, 2007


PBS posted:

From the error it sounds like it doesn't like your filter.

""A parameter cannot be found that matches parameter name 'eq'. (A parameter cannot be found that matches parameter name 'eq'.)""

Can you try another filter format? Or provide the full body of relevant errors? $error[0] | select *
I think this is everything

writeErrorStream : True
PSMessageDetails :
Exception : Microsoft.PowerShell.Commands.WriteErrorException: A parameter cannot be found that matches
parameter name 'eq'.
TargetObject :
CategoryInfo : InvalidData: (:) [Write-Error], Error Creating Service Request
FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Create-SCSMServiceRequest
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at Create-SCSMServiceRequest, C:\ProgramData\Microsoft\System Center\Orchestrator\7.2\SMA\Sandbo
xes\yteug04o.u1l\temp\srycaoqe.mpc\Create-SCSMServiceRequest.ps1: line 192
at <ScriptBlock>, C:\ProgramData\Microsoft\System Center\Orchestrator\7.2\SMA\Sandboxes\yteug04o
.u1l\temp\srycaoqe.mpc\Create-SCSMServiceRequest.ps1: line 198
at <ScriptBlock>, <No file>: line 38
PipelineIterationInfo : {0, 0}

/e- changed the filter syntax to {(logic)} and got:
exception
property (property)
output

writeErrorStream : True
PSMessageDetails :
Exception : Microsoft.PowerShell.Commands.WriteErrorException: property
TargetObject :
CategoryInfo : InvalidData: (:) [Write-Error], Error Creating Service Request
FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Create-SCSMServiceRequest
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at Create-SCSMServiceRequest, C:\ProgramData\Microsoft\System Center\Orchestrator\7.2\SMA\Sandbo
xes\yteug04o.u1l\temp\rpg2k2z4.dsv\Create-SCSMServiceRequest.ps1: line 192
at <ScriptBlock>, C:\ProgramData\Microsoft\System Center\Orchestrator\7.2\SMA\Sandboxes\yteug04o
.u1l\temp\rpg2k2z4.dsv\Create-SCSMServiceRequest.ps1: line 198
at <ScriptBlock>, <No file>: line 38
PipelineIterationInfo : {0, 0}

/e- first error when chaning ID to display name so it's not the guid :downs:

Submarine Sandpaper fucked around with this message at 15:10 on Oct 29, 2018

anthonypants
May 6, 2007

by Nyc_Tattoo
Dinosaur Gum

Submarine Sandpaper posted:

I think this is everything

writeErrorStream : True
PSMessageDetails :
Exception : Microsoft.PowerShell.Commands.WriteErrorException: A parameter cannot be found that matches
parameter name 'eq'.
TargetObject :
CategoryInfo : InvalidData: (:) [Write-Error], Error Creating Service Request
FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Create-SCSMServiceRequest
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at Create-SCSMServiceRequest, C:\ProgramData\Microsoft\System Center\Orchestrator\7.2\SMA\Sandbo
xes\yteug04o.u1l\temp\srycaoqe.mpc\Create-SCSMServiceRequest.ps1: line 192
at <ScriptBlock>, C:\ProgramData\Microsoft\System Center\Orchestrator\7.2\SMA\Sandboxes\yteug04o
.u1l\temp\srycaoqe.mpc\Create-SCSMServiceRequest.ps1: line 198
at <ScriptBlock>, <No file>: line 38
PipelineIterationInfo : {0, 0}

/e- changed the filter syntax to {(logic)} and got:
exception
property (property)
output

writeErrorStream : True
PSMessageDetails :
Exception : Microsoft.PowerShell.Commands.WriteErrorException: property
TargetObject :
CategoryInfo : InvalidData: (:) [Write-Error], Error Creating Service Request
FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Create-SCSMServiceRequest
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at Create-SCSMServiceRequest, C:\ProgramData\Microsoft\System Center\Orchestrator\7.2\SMA\Sandbo
xes\yteug04o.u1l\temp\rpg2k2z4.dsv\Create-SCSMServiceRequest.ps1: line 192
at <ScriptBlock>, C:\ProgramData\Microsoft\System Center\Orchestrator\7.2\SMA\Sandboxes\yteug04o
.u1l\temp\rpg2k2z4.dsv\Create-SCSMServiceRequest.ps1: line 198
at <ScriptBlock>, <No file>: line 38
PipelineIterationInfo : {0, 0}

/e- first error when chaning ID to display name so it's not the guid :downs:
Is this line 192 or 198?
code:
$SRProjection = Get-SCSMObjectProjection -ProjectionName $SRTypeProjection.Name -filter “ID -eq $SRID” @connection
If so, just change those to normal double-quotes like the one for $SRObject.

Submarine Sandpaper
May 27, 2007


anthonypants posted:

Is this line 192 or 198?
code:
$SRProjection = Get-SCSMObjectProjection -ProjectionName $SRTypeProjection.Name -filter “ID -eq $SRID” @connection
If so, just change those to normal double-quotes like the one for $SRObject.

192 is the error catch, 198 is the call to the create-scsmservicerequest function.

That helped though, was (and I hope I'm done with this) able to fix it by:

code:
 #Uses ID to pull created ticket as projection. 
    $SRProjection = Get-SCSMObjectProjection -ProjectionName $SRTypeProjection.Name -filter "ID -eq '$SRID'" @connection    
    
    #pulls template and applies to ticket projection      
    Set-SCSMObjectTemplate -Projection $SRProjection -Template $SRTemplate @connection
    Write-Output "$TemplateName applied to Service Request $SRID"

    #Pulls ticket as object to apply relationships and changes later
    $SRObject = get-scsmobject -Class $SRClass -filter "ID -eq $SRID" @connection
Not sure why the first filter wants SRID in singles and the second doesn't. Maybe an issue with smlets?

anthonypants
May 6, 2007

by Nyc_Tattoo
Dinosaur Gum

Submarine Sandpaper posted:

192 is the error catch, 198 is the call to the create-scsmservicerequest function.

That helped though, was (and I hope I'm done with this) able to fix it by:

code:
 #Uses ID to pull created ticket as projection. 
    $SRProjection = Get-SCSMObjectProjection -ProjectionName $SRTypeProjection.Name -filter "ID -eq '$SRID'" @connection    
    
    #pulls template and applies to ticket projection      
    Set-SCSMObjectTemplate -Projection $SRProjection -Template $SRTemplate @connection
    Write-Output "$TemplateName applied to Service Request $SRID"

    #Pulls ticket as object to apply relationships and changes later
    $SRObject = get-scsmobject -Class $SRClass -filter "ID -eq $SRID" @connection
Not sure why the first filter wants SRID in singles and the second doesn't. Maybe an issue with smlets?
That's weird, because single-quotes typically means what's inside doesn't get parsed. So that variable might not get expanded.

mystes
May 31, 2006

anthonypants posted:

That's weird, because single-quotes typically means what's inside doesn't get parsed. So that variable might not get expanded.
Are you talking about "ID -eq '$SRID'"? Putting single quotes inside a string won't magically prevent variables from getting expanded.

Potato Salad
Oct 23, 2014

nobody cares


New Yorp New Yorp posted:

That's what I thought. Can't use the IP directly, so I guess I'll either deal with it or build something to safely manipulate entries in the hosts file. Bummer.

do you happen to have dsc push or sccm?

PBS
Sep 21, 2015

mystes posted:

Are you talking about "ID -eq '$SRID'"? Putting single quotes inside a string won't magically prevent variables from getting expanded.

Single quotes tells powershell to interpret the contents literally.

PS C:\Users\PBS> $test = 123
PS C:\Users\PBS> Write-Output $test
123
PS C:\Users\PBS> Write-Output '$test'
$test

In the case of "ID -eq '$SRID'", that should be interpreted as, Does ID equal the string $SRID?

mystes
May 31, 2006

PBS posted:

Single quotes tells powershell to interpret the contents literally.

PS C:\Users\PBS> $test = 123
PS C:\Users\PBS> Write-Output $test
123
PS C:\Users\PBS> Write-Output '$test'
$test

In the case of "ID -eq '$SRID'", that should be interpreted as, Does ID equal the string $SRID?
You either haven't read what I was replying to and/or you are confused.

This is what the original line in question was.
code:
$SRProjection = Get-SCSMObjectProjection -ProjectionName $SRTypeProjection.Name -filter "ID -eq '$SRID'" @connection
Note that in this line, the string literal "ID -eq '$SRID'" (with the double quotes as part of the literal) is the filter parameter.

This means 1) the contents of this string are not even evaluated as powershell code. 2) Even they were actually later evaluated as powershell code that's irrelevant, because when the entire literal is evaluated, the variable $SRID will be substituted. Again, the presence of single quotes inside the string is irrelevant.

E.g.:
code:
> $s = "ID -eq '$SRID'"                                                                                                                                                                        
> $s                                                                                                                                                                                           
ID -eq 'hi'

PBS
Sep 21, 2015

You're right, I didn't know single quotes behaved in that way within double quotes actually. Anyone know how it works that way?

mystes
May 31, 2006

PBS posted:

You're right, I didn't know single quotes behaved in that way within double quotes actually. Anyone know how it works that way?
Because you're thinking about it backwards. Single quotes don't stop variables from being expanded or something like that. Rather, only string literals surrounded by double quotes get expanded, and the rules for this don't involve whether quotes (either single or double) appear within the string that's being expanded.

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.
What is the proper syntax to switch "\\server\e$\" with "s3://bucketname/" ?




I am writing a script that will parse a list of directory_path+filenames and will copy them to an S3 bucket. The problem is that the list is of windows files in the form of:

\\server\e$\folder name\folder name2\foldername3\etc\file name.txt

or some variant thereof (containing a server name, a drive share, a bunch of folders and then a file name)

and the destination needs to be in the form of

s3://bucket-name/folder name/folder name2/foldername3/etc/file name.txt



What I'd planned on doing is reading the file name and doing a bunch of -replace strings to get the command syntax correct then do a

aws cp $oldString $newString to get it copied.


The problem is I cannot figure out the syntax of the replace command to switch "\\server\e$\" with "s3://bucketname/". I've tried single quotes to avoid having e$ getting parsed as regex and a few other things, but I can't get it working.

mystes
May 31, 2006

Agrikk posted:

What is the proper syntax to switch "\\server\e$\" with "s3://bucketname/" ?




I am writing a script that will parse a list of directory_path+filenames and will copy them to an S3 bucket. The problem is that the list is of windows files in the form of:

\\server\e$\folder name\folder name2\foldername3\etc\file name.txt

or some variant thereof (containing a server name, a drive share, a bunch of folders and then a file name)

and the destination needs to be in the form of

s3://bucket-name/folder name/folder name2/foldername3/etc/file name.txt



What I'd planned on doing is reading the file name and doing a bunch of -replace strings to get the command syntax correct then do a

aws cp $oldString $newString to get it copied.


The problem is I cannot figure out the syntax of the replace command to switch "\\server\e$\" with "s3://bucketname/". I've tried single quotes to avoid having e$ getting parsed as regex and a few other things, but I can't get it working.
Single/double quotes are sort of a red herring here. The issue isn't escape sequences (which start with backticks not backslashes and are interpreted when using double quotes when the string literal is evaluated), but rather that the replace operator is interpreting the resulting string as a regular expression, which requires you to escape certain characters with backslashes but is not something that you can control by using single quotes.

You either need to use [regex]::Escape(), properly escape the string by hand as a regular expression, or use another method.

code:
> $s = '\\server\e$\folder name\folder name2\foldername3\etc\file name.txt'
> $s -replace [regex]::Escape('\\server\e$\'), 's3://bucketname/'                                                                                                                              
s3://bucketname/folder name\folder name2\foldername3\etc\file name.txt

> [regex]::Escape('\\server\e$\')
\\\\server\\e\$\\
(This still leaves inconsistent slashes that you may need to fix)

Edit: Incidentally, if you don't want to use replace, maybe something like this will work for you:
code:
> [System.IO.Path]::Combine('s3://bucketname/', ([Uri]'\\server\e$\').MakeRelative('\\server\e$\folder name\folder name2\foldername3\etc\file name.txt'))
s3://bucketname/folder%20name/folder%20name2/foldername3/etc/file%20name.txt

mystes fucked around with this message at 02:48 on Oct 31, 2018

Pile Of Garbage
May 28, 2007



Don't use the -replace operator, just use the Replace() method:

code:
PS C:\> $foo = '\\server\e$\folder name\folder name2\foldername3\etc\file name.txt'
PS C:\> $foo.Replace('\\server\e$\', 's3://bucketname/').Replace('\', '/')
s3://bucketname/folder name/folder name2/foldername3/etc/file name.txt
Edit: lol lot of overthinking above me.

Pile Of Garbage fucked around with this message at 13:29 on Oct 31, 2018

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.
Thank you for these responses.

My next question if the command I'm using is

aws s3 cp $line $newline

Where $line = \\server\e$\folder name\folder name2\foldername3\etc\file name.txt

and $newline is s3://bucketname/folder name/folder name2/foldername3/etc/file name.txt

How do I encapsulate the output of each string to account for the spaces in the file path?

I need the final output to be:

aws s3 cp "\\server\e$\folder name\folder name2\foldername3\etc\file name.txt" "s3://bucketname/folder name/folder name2/foldername3/etc/file name.txt"

anthonypants
May 6, 2007

by Nyc_Tattoo
Dinosaur Gum

Agrikk posted:

Thank you for these responses.

My next question if the command I'm using is

aws s3 cp $line $newline

Where $line = \\server\e$\folder name\folder name2\foldername3\etc\file name.txt

and $newline is s3://bucketname/folder name/folder name2/foldername3/etc/file name.txt

How do I encapsulate the output of each string to account for the spaces in the file path?

I need the final output to be:

aws s3 cp "\\server\e$\folder name\folder name2\foldername3\etc\file name.txt" "s3://bucketname/folder name/folder name2/foldername3/etc/file name.txt"
aws s3 cp "$line" "$newline"

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.

anthonypants posted:

aws s3 cp "$line" "$newline"

That's not working. It's simply passing the line

aws s3 cp "$line" "$newline"

to the AWS CLI.

Submarine Sandpaper
May 27, 2007


aws s3 cp "`"$line`"" "`"$newline`""

those are the escapes you need if i'm reading you right. surround in more quotes if you're using it like a filter string.

Submarine Sandpaper fucked around with this message at 01:05 on Nov 1, 2018

The Fool
Oct 16, 2003


I recently wrote up a script to migrate our on-prem distribution lists to O365 with the ultimate goal of eliminating our hybrid exchange server.

As part of the script I wanted to be able to connect to on-prem exchange and O365 at the same time, so combined a couple different methods that I found and came up with this:

code:
    Write-Host "Connecting to O365.."
    $O365Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Credential -Authentication Basic -AllowRedirection
    Write-Host "Connecting to on-prem Exchange server.."
    $OnPremSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://onpremserver.contoso.com/PowerShell/ -Authentication Kerberos -Credential $Credential
    Write-Host "Importing commands for O365.."
    Import-Module(Import-PSSession $O365Session -DisableNameChecking -AllowClobber) -Global -Prefix O365
    Write-Host "Importing commands for on-prem Exchange server.."
    Import-Module(Import-PSSession $OnPremSession -DisableNameChecking -AllowClobber) -Global -Prefix OnPrem
Which allows me to do stuff to both O365 and on-prem exchange at will.

code:
    Write-Host "Getting info from on-prem list: $DistributionList"
    $OnPremList = Get-OnPremDistributionGroup $DistributionList
    Write-Host "Getting info from O365 list: $DistributionList"
    $O365List = Get-O365DistributionGroupMember $DistributionList
Don't forget to close your connections.
code:
    Write-Host "Closing connections.."
    Get-PSSession | ForEach-Object {Remove-PSSession $_}

The Fool fucked around with this message at 21:51 on Nov 1, 2018

CzarChasm
Mar 14, 2009

I don't like it when you're watching me eat.
I have what I hope is a fairly simple question. I'm brand new to powershell, so I might be missing something super obvious.

I have a powershell script that connects to our exchange server from O365, passes credentials specific for one account, looks at every message and copies any attachments to a network location. This works fine.

What I want it to do next is to build a text file with specific information from the email. So grab the sender name, email address, date created, date received, and the body of the message.

I have it built so it is using an Invoke-RestMethod and points to the URL for Office 365 and then pulls the info for the matching message.ID. What I can't figure out is how to get it to pull the value of a field, rather than the whole thing.

See my code below.
code:
$query = $url + "/" + $message.Id + "/Sender/EmailAddress/Name"
$SenderName = Invoke-RestMethod $query -Credential $cred
When I process this, $SenderName equals
code:
@{@odata.context=https://outlook.office365.com/api/v1.0/$metadata#Me/Messages('AAMkADYwYjA2ZmU1LTNiYjYtNGNkNy04NmZhLTg5OTUyNmJjMzQzYQBGAAAAAAANLWq9xYZHRIIS_bU2vXqpBwBKIT9w7chNTpcLmKKB9buvAAAAAAEMAABKIT9w7chNTpcLmKKB9buvAAABZ1PNAAA%3D')/Sender/EmailAddress/Name; value=Bart J. Simpson}
What I want is just that last nugget. The "Bart J. Simpson" bit. But I'm just beating my head against a wall. I can't figure out out to grab that VALUE. Do I have this backwards? Can I do something like this?

code:
$query = $url + "/" + $message.Id + "/Sender/EmailAddress/Name"
$TEMP = Invoke-RestMethod $query -Credential $cred
$SenderName = $Temp.Value
EDIT Nevermind. This was exactly it. Though there might be a more efficient way to do this. Can I do something like

code:
$query = $url + "/" + $message.Id
$TEMP = Invoke-RestMethod $query -Credential $cred
$SenderName = $Temp.sender.emailaddress.name.value
$SenderEamil = $Temp.sender.emailaddress.address.value
$DateSent = $Temp.datetimecreated.value

CzarChasm fucked around with this message at 17:45 on Nov 5, 2018

Pile Of Garbage
May 28, 2007



It depends on what object is being returned by Invoke-RestMethod. From the cmdlet's help page:

quote:

PowerShell formats the response based to the data type. For an RSS or ATOM feed, PowerShell returns the Item or Entry XML nodes. For JavaScript Object Notation (JSON) or XML, PowerShell converts (or deserializes) the content into objects.

If the REST response is being properly deserialized then you should be able to use dot-notation to access the properties. Use the GetType() method to check what object(s) are being returned and pipe to Get-Member to discover properties:

code:
$query = $url + "/" + $message.Id
$Temp = Invoke-RestMethod $query -Credential $cred
$Temp.GetType()
$Temp | Get-Member

Adbot
ADBOT LOVES YOU

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

CzarChasm posted:

[snip]
code:
$query = $url + "/" + $message.Id + "/Sender/EmailAddress/Name"
$TEMP = Invoke-RestMethod $query -Credential $cred
$SenderName = $Temp.Value
EDIT Nevermind. This was exactly it. Though there might be a more efficient way to do this. Can I do something like

code:
$query = $url + "/" + $message.Id
$TEMP = Invoke-RestMethod $query -Credential $cred
$SenderName = $Temp.sender.emailaddress.name.value
$SenderEamil = $Temp.sender.emailaddress.address.value
$DateSent = $Temp.datetimecreated.value
Looking at the O365 API Documentation, you can use $select to get only the specific properties that you want. So you'd want to do something like
code:
#untested because I don't have access to O365
$query = $url + "/" + $message.Id + "=?`$select=Sender/EmailAddress,DateTimeCreated"
$queryResponse = Invoke-RestMethod $query -Credential $cred
And then do what Pile Of Garbage said to see how the result is deserialized.

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