check processor architecture and proceed with if statement - powershell

i know that here are a lot of examples how to get the processor architecture.
this should get the type with true or false checking on x64
my question is: how do i get this output into a if statement?
example: if it is an 64bit processor THEN perform a few steps and if it is 32bit then perform other steps. how can i go on further?
i tried a few versions of code but also got true or false back which is ok but how to go on further?
can you help me out guys?
thanks

thank you all.
i solved it by using the following:
$os_type = (Get-WmiObject -Class Win32_ComputerSystem).SystemType -match ‘(x64)’
if ($os_type -eq "True") {
Write-Host "i am an 64bit OS"
write-host $os_type }
else {
$os_type = (Get-WmiObject -Class Win32_ComputerSystem).SystemType -match ‘(x86)’
if ($os_type -eq "True") {
Write-Host "i am a 32 Bit OS" }

[System.Environment]::Is64BitProcess returns true or false, so it's a very simple if statement.
if ([System.Environment]::Is64BitProcess) {
# Do 64-bit stuff
} else {
#Do 32-bit stuff
}
You didn't specify which of the "lot of examples" you're using, so I showed the method I use.

Could also use the environment variables.
$Is64bitProcess = $env:PROCESSOR_ARCHITECTURE -eq 'AMD64'
$Is64bitOs = $Is64bit = $env:PROCESSOR_ARCHITEW6432 -eq 'AMD64'

thanks for your input!
i tried for example this:
Thank you for your answer! i tried for example the following:
echo "check if 32 or 64bit OS"
$var = (Get-WmiObject -Class Win32_ComputerSystem).SystemType -match ‘(x64)’
if ($var = "True") {echo "i am an 64bit OS"
#setting the current directory as the directory the script is in
$sourcenssm= Split-Path -Parent $MyInvocation.MyCommand.Definition
#setting the targetdirectory for nssm
$targetnssm="C:\Users\cp\Desktop\nssm.exe"
#setting the current directory as the directory the script is in
$sourcewts= Split-Path -Parent $MyInvocation.MyCommand.Definition
#setting the targetdirectory for wtswatchdog
$targetwts="C:\Windows\wtswatchdog.exe"
#copying nssm to target - WORKING
if (-not(Test-path $targetnssm)) {Copy-item -Path $sourcenssm\nssm.exe -Destination $targetnssm}
#copying wtswatchdog to target - CHECK!
if (-not(Test-path $targetwts)) {Copy-item -Path $sourcewts\wtswatchdog.exe -Destination $targetwts}
}
but it gives me everytime 64 bit as an output also if i am checking
echo "check if 32 or 64bit OS"
$var = (Get-WmiObject -Class Win32_ComputerSystem).SystemType -match ‘(x86)’
if ($var = "True") {echo "i am an 64bit OS"}
then it is also going to the echo-part.

Alroc's answer works for powershell 3.0 or above i believe. In case there is an issue with that another approach would be this:
$architecture = (Get-WmiObject win32_processor | Where-Object{$_.deviceID -eq "CPU0"}).AddressWidth
If ($architecture -eq 64) {
# Do 64-bit stuff
} else {
#Do 32-bit stuff
}

Related

Check if program is installed if so go to next powershell

I've googled and not found anything useful to me.
I have 4 msi files I want to install but would like to check if some of it is installed on the computer.
Example:
check if program 1 is installed, if not install it and go to and install program 2.
However if it's not installed, install it and go to program 2 and do the same test there.
Execute-MSI -Action Install -Path "$dirFiles\Program1"
Execute-MSI -Action Install -Path "$dirFiles\Program2"
Execute-MSI -Action Install -Path "$dirFiles\Program3"
Execute-MSI -Action Install -Path "$dirFiles\Program4"
If you know the GUID, you could test path the uninstall key. Also don't forget that if your OS is 64 bit, there will be the same key in WOW6432Node for 32 bit apps.
$uninstallkey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\"
$uninstall32key = "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
#Example 64-bit app
$app1guid = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
if (!(Test-Path "$uninstallkey\$app1guid)) {Execute-MSI -Action Install -Path "$dirFiles\Program1"}
#Example 32-bit app
$app2guid = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
if (!(Test-Path "$uninstall32key\$app2guid)) {Execute-MSI -Action Install -Path "$dirFiles\Program1"}
Without knowing anything about your applications, there are two easy options I can think of.
1) Read a log file, looking for a pattern / string - check 6 times (configure as needed) and fail if it doesn't complete. If it does, move on to the next install and do the same check
$LOGFILE = 'C:\Somewhere.log'
$Complete = 'no'
$Counter = 1
$max = 6
Start-Sleep 10
DO {
$Check = SELECT-STRING -pattern 'status: 0.' -path $logfile -quiet
write-host $Check
If (($Check) -eq $True) {
Set-Variable -name Complete -Value "yes"
}
Else {Set-Variable -name Complete -Value 'no'}
Write-host $Counter
Start-Sleep 20
$Counter++
}
while ($Complete -eq 'no')
If (($Counter) -eq $max) {
Throw 'Installation failed, check the error log'
}
Option 2)
If you know what directories it creates or even a file count, can do something like the above with count instead of a file read
$PRDIR = "D:\Folder"
If (($PRDIR.Count) -gt 2)
{
Do something
}
Else
{
Do something else
{
Hope that helps!
R
You can use WMI to check if your MSIs are installed or not. Example:
$products = Get-WmiObject -Class win32_product | Where-Object { $_.Name -like "*someName*" } | Select-Object *
You might extend the Where-Object clause with additional patterns to query for (e.g. via $_.Name -like "*Sw1*" -or $_.Name -like "*Sw2*" ). $products should be an array including the findings, which you can use to check if the requested SW is installed or not. Example:
PS> $found = $results.Where({ $_.Name -like "*sw1*"})
PS> if ($found) { Write-Host "Found" }
Hope that helps

Get Folder NTFS ACL on long path name

I have a PS script that will return NTFS ACLs if an individual user is assigned, works well until I hit a path exceeding 260 characters. I've found a lot of information on the path too long problem and some work-arounds but I'm struggling to integrate a solution into my script. Any suggestions?
Thanks!
$DateStart = Get-Date
$Path = "E:\"
$PermittedOU1 = "OU=Groups,dc=chiba,dc=localt"
$PermittedOU3 = "OU=System Accounts,OU=Accounts,dc=chiba,dc=local"
$PermittedACL1 = get-adgroup -Filter * -SearchBase $PermittedOU1
$PermittedACL3 = get-aduser -Filter * -SearchBase $PermittedOU3
$ObjectPathItem = Get-ChildItem -path $Path -Recurse | where-object {$_.PsIsContainer} | foreach- object -process { $_.FullName }
$howmany=0
$Logfilename = "C:\Users\administrator\Documents\$(get-date -f yyyy-MM-dd-hh-mm).csv"
Add-Content $Logfilename "$DateStart`n"
$totalfolders=0
$i=0
ForEach ($Folder in $ObjectPathItem)
{
$totalfolders++
}
Foreach ($Folder in $ObjectPathItem)
{
$ObjectACL = Get-ACL -Path $Folder
$i++
$howmany=0
Write-Progress -id 1 -Activity "Folder Recursion" -status "Folders Traversed: " -PercentComplete (($i / $totalfolders) * 100)
Foreach ($ACL in $ObjectACL.access)
{
$ACLstring = $ACL.identityreference.Value
$ACLstring = $ACLstring.Replace("CHIBA\","")
if (($ACLstring -notin $PermittedACL1.name)`
-and ($ACLstring -notin $PermittedACL3.SamAccountName)`
-and ($ACLstring -notin "NT AUTHORITY\SYSTEM") `
-and ($ACLstring -notin "BUILTIN\Administrators") `
-and ($ACLstring -notin "CREATOR OWNER"))
{
$newline = "`"$Folder`"" + "," + "$ACLString"
Add-Content $Logfilename "$newline"
$howmany+=1
}
else {
$howmany+=1
}
}
}
$DateEnd = Get-Date
Add-Content $Logfilename "`n`n$DateEnd"
One option you can usually use is to create a mapped drive using New-PSDrive. Something like:
Try{
$ObjectACL = Get-ACL -Path $Folder
}
Catch{
$SubPathLength = $Folder.FullName.substring(0,200).LastIndexOf('\')
$NewTempPath = $Folder.FullName.SubString(0,$SubPathLength)
New-PSDrive -Name Temp4ACL -Provider FileSystem -Root $NewTempPath
$ObjectACL = Get-ACL "Temp4ACL:$($Folder.FullName.SubSTring($SubPathLength,$Folder.FullName.Length-$SubPathLength))"
}
That will find the last \ before the 200th character in the path, grab a substring of the full path up to the end of that folder's name and create a temp drive of it, then get the ACL based off the temp drive and the remaining path. So this path:
C:\Temp\Subfolder\Really Long Folder Name\Another Subfolder\ABCDEFGHIJKLMNOPQRSTUVWXYZ\We Are Really Pushing It Now\Im Running Out Of Folder Name Ideas\Hello My Name Is Inigo Montoya\You Killed My Father Prepare To Die\ReadMe.txt
Gets cut at the second to last backslash. I would end up getting the ACL from:
Temp4ACL:\You Killed My Father Prepare To Die\ReadMe.txt
Easy way is to use "\\?" to support 32,767 characters.
$folder = "C:\MyFolder"
icacls "\\?\$folder"
https://msdn.microsoft.com/en-us/library/windows/desktop/aa364963(v=vs.85).aspx
In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function (GetFullPathNameW), and prepend "\\?\" to the path.
Okay, this question is quite old but for those coming here as of today like myself I provide this information that I found through Google:
Microsoft Technet Script Center lists a "File System Security PowerShell Module" which claims that since version 3.0 it "leverages the AlphaFS (http://alphafs.codeplex.com) to work around the MAX_PATH limitation of 260 characters". At the time of this writing the module is at version 4.2.3.
The general idea of this module is described as "PowerShell only offers Get-Acl and Set-Acl but everything in between getting and setting the ACL is missing. This module closes the gap."
So without having tried this myself I suppose it should help in solving the OPs problem.
The module is also featured in a post by the "Hey, Scripting Guy! Blog".

How to catch machine name on copy-item error?

I'm trying to write a file and delete a file on multiple remote Windows machines. If the machine is not available, ie. not on line I want to capture that in an error log so that I have a list of problematic machine names to send to a help desk. It's probably ugly but I'm close to having something that works. Any clarification would be appreciated.
$from="D:\whatever\machinfo"
$to="\\$machine\c\\scripts\"
output_file="D:\whatever\reports\$machine_writeerror.txt"
foreach($machine in(gc d:\whatever\machinfo\testworkstations.txt))
{
$machine
IF (!$to)
{
Copy-Item D:\whatever\machinfo\010RunGetmachinfo.bat \\$machine \c\scripts -verbose
# $errormsg="destination not found"
$machine > output_file
}
ELSE
{
# DO NOTHING
Remove-Item \\$machine\c\scripts\000dontrun.bat
}
}
OK, I've rewritten this but I'm not doing something right. I want an unique error file that contains either a single file for each machine connection failure or one file that contains the computername of all machines that could not be connected to. I think the following is close (but not right).
$logfile="D:\Projects\StoreControls\machinfo\reports\"+$machine+"_writeerror.txt"
foreach($machine in(gc d:\projects\StoreControls\machinfo\testworkstations.txt))
{
$machine
If ( (Test-Connection -Computername $machine -Quiet -Count 1) -eq "False"){
$machine > $logfile}
Else{
Remove-Item \\$machine\c\scripts\tasks\000dontStart.bat
Copy-Item D:\Projects\StoreControls\machinfo\010RunPCsNServersGetmachinfo.bat \\$machine\c\scripts\tasks\
}
}
Changed "False" to $False after reading more on Test-Connection. Works! Thank you!
you can test the correct execution of a command by testing the automatic variable $?
so you can use something like
Copy-Item D:\whatever\machinfo\010RunGetmachinfo.bat \\$machine\c\scripts
if($? -eq $false){
# copy has failed
"Copy error on $machine" |out-file d:\whatever\reports\$machine_writeerror.txt
}
by the way, a more efficient way could be to ping the host and see if it's alive :
if ( (Test-Connection -ComputerName $machine -Quiet -Count 1) -eq $false){
#host not available
}

IF Statement not working in Powershell

I've been trying to get an IF-ELSE clause to work within my little powershell v2 script, and I think I'm having some problems with my parsing. Here's the code I have currently:
$dir = test-path C:\Perflogs\TestFolder
IF($dir -eq "False")
{
New-Item C:\Perflogs\TestFolder -type directory
get-counter -counter $p -Continuous | Export-Counter C:\PerfLogs\TestFolder\Client_log.csv -Force -FileFormat CSV -Circular -MaxSize $1GBInBytes
}
Else
{
get-counter -counter $p -Continuous | Export-Counter C:\PerfLogs\TestFolder\Client_log.csv -Force -FileFormat CSV -Circular -MaxSize $1GBInBytes
}
So basically I want it to establish the $dir variable as testing to see if the path I want exists. If it doesn't, it should create that folder and run the counters. If it does, it should not create the folder but should still run counters.
I've got $p defined elsewhere, and the get-counters statement works fine. Right now, whether the folder exists or not I'm getting an error about new-item not working.
Am I using the wrong operator for -eq after doing that test?
You should have:
if ($dir -eq $false)
because the string "False" is not equal to the boolean value $false.
Try changing this:
IF($dir -eq "False")
to this:
IF($dir -eq $false)
x0n already answered, so I wont repeat that, but I noticed another "Gotcha" you should be aware of.
Your code is trying to test for the existence of a directory "TestFolder", however you test-path command is not restricted to checking only for directories. Meaning, if you actually happen to have a file by the same name "TestFolder" it will still return true.
To be more careful, you should add the "-PathType Container" switch so that it will fail if there is a file by that name and only pass if there is a directory by that name.
$dir = test-path C:\Perflogs\TestFolder -PathType Container
In addition to the other answers about $false, I've had syntax issues with v3. Specifically
if($dir -eq $false)
{
didn't work.
if($dir -eq $false){
did work. YMMV, but you've been warned.
It might work
If($? -ne 0)
if the given condition is false, which is defined in earlier variables(This is not for the above question)
If($dir -contains 'False')

file location different on computers and space issues

I have the below code and currently checks computer for version info and service status.
The problem I have is that servers have the located .exe in different places:
C:\program files\snare\snarecore.exe
C:\program files (x86)\snare\snarecore.exe
D:\apps\snare\snarecore.exe
How do I get the script below to run the right version? I think I can use the path that the service is checking? I am doing this all remotly and have rights to the server and works fine - but I am having to possiblt make three (or more!) scripts just based on all three locations of where the executable is!
Also, for the ones that have a space in the name (../program file..) where do I put the quotes so that powershell can read the whole line and not error out due to the space in the name?
CODE:
clear
$ErrorActionPreference = "silentlycontinue"
$Logfile = "C:\temp\output_cdrive.log"
Function LogWrite
{
param([string]$logstring)
Add-Content $Logfile -Value $logstring
}
$computer = Get-Content -Path c:\temp\servers2.txt
foreach ($computer1 in $computer){
$Service = Get-WmiObject Win32_Service -Filter "Name = 'Snare'" -ComputerName $computer1
if (test-connection $computer1 -quiet)
{
$version = (Get-Command ""\\$computer1\c$\Program Files (x86)\Snare\SnareCore.exe"").FileVersionInfo.FileVersion
if($Service.state -eq 'Running')
{
LogWrite "$computer1 STARTED $version"
}
else
{
LogWrite "$computer1 STOPPED $version"
}
}
else
{
LogWrite "$computer1 is down" -foregroundcolor RED
}
}
Thanks,
you can check the pathname property of you service to get the exe location :
PS>(Get-WmiObject Win32_Service -Filter "name='spooler'").pathname
C:\Windows\System32\spoolsv.exe
The obvious solution is to use a path variable, assign that variable each of the three different paths in turn, and write your actual checks as a function using that variable.
You can escape the double quotes using the backtick:
"`"\\$computer1\c$\Program Files (x86)\Snare\SnareCore.exe`""