file location different on computers and space issues - powershell

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`""

Related

How can you replace multiple UNC paths of mapped drives via registry using PowerShell?

Our servers team has implemented a DFS, but users across the company still have drives mapped using the server name(s) at various sites. I'd like to push out a PS script that updates a SINGLE registry value (per drive).
My goal is to look through each drive letter key, if the key exists and the remote path starts with the server name then replace it with, the DFS name \\domain.com\SITE\+remainder of the path. This way users keep the same drive letters without having to "remap" their drives
Using Denver office as an example...
$OldServer = "\\denvernas01\"
$NewServer = "\\domain.com\DEN\"
$DriveLetterArray = "A","B","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"
foreach ($DriveLetter in $DriveLetterArray)
{ $Drives = Get-ItemPropertyValue HKCU:\Network\$DriveLetter -Name RemotePath -ErrorAction SilentlyContinue
$RemainingPath = $Drives.Replace($OldServer,"")
foreach ($Drive in $Drives)
{ if ($Drive -like "*$OldServer*")
{ Set-ItemProperty HKCU:\Network\$DriveLetter -Name RemotePath -Value "$NewServer"+"$RemainingPath" }}}
EDIT
^^^This currently works, but only if the server name in RemotePath is all lower case. I.e. the server variables are case sensitive. Any thoughts on how to define the $OldServer & $NewServer variables so it will work with case variations???? e.g. Denvernas01, DENVERNAS01 (or anything inbetween)
I've come across a few threads discussing New-PSDrive, Get-WMIObject, etc, but I'd really like to just replace this one registry value. This would be a good "patch" that would take some stress off of our desktop support team. Trust me - I'll be advocating for GPO to push out common mapped drives once this is all over.
Any feedback is greatly appreciated. Thank you!
If anyone out there is interested, this is what I ended up with, and it worked like a charm. Thought I'd share...
$OldServer = '\\denvernas01'
$NewServer = '\\Domain.com\DEN'
$DriveLetterArray = "A","B","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"
foreach ($DriveLetter in $DriveLetterArray){
$DrivePath = $null; $ConvertedPath = $null
$DrivePath = Get-ItemPropertyValue -Path "HKCU:\Network\$DriveLetter" -Name "RemotePath" -ErrorAction SilentlyContinue
if ($DrivePath -eq $null) {continue}
#Replace Old Drive Path
if ($DrivePath -like "*${OldServer}*") {
$ConvertedPath = $DrivePath -ireplace [regex]::Escape("$Oldserver"), $NewServer
$ConvertedPath
Set-ItemProperty -Path "HKCU:\Network\$DriveLetter" -Name "RemotePath" -Value "${ConvertedPath}"
} else {
#Write-Host "no match"
continue
}
#Write-Host ""
}
#Remove previous mountpoints
Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\* | Where-Object Name -Match "##denvernas" | Remove-Item

writing output file as .txt or .csv to script containing multiple conditions

I have written a script which checks a service status, tests two paths and also tests a registry value. Currently I am getting output on the power shell console (that could be because I am using write-output command).
Is there any way to write the single one page output to a file?
I am struggling to find a way to out-file entire output to a file.
Below is the script.
$testpath = Test-Path "C:\test"
$testpath2 = test-path "C:\test"
$mcshieldk = Get-Service -Name mcshield | select Name
$internet = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\internet explorer").MkEnabled $hostname = hostname Write-Host "hostname of comuter is" $hostname if (Test-Path $Machinetype)
{}
else { Write-Host "internet is" $internet }
if ($testpath -eq $true -and $testpath2 -eq $true)
{ Write-Host "test and test1 folder exists" -ForegroundColor Green }
else{ Write-Host "folder does not exists" -ForegroundColor Red } if($mcshield.Name -eq "mcshield") { Write-Host "mcshield service exists" }
else { Write-Host "mcshield does not exists" }
Below is the console output
hostname of comuter is Server1
internet is Yes
test and test1 folder exists
mcshield does not exists
Swap out your Write-Host cmdlets or add in another line with the following:
"Your output text $YourVariable" | Out-File -FilePath "C:\Log.txt" -Append -Encoding utf8
This will append a string to the end of the log file C:\Log.txt. Note, missing the -Append parameter will cause the file to be overwritten.
You can also use the follow to give the same affect:
"Your output text $YourVariable" >> "C:\Log.txt"
But be carefully not to mix the two methods as you might get encoding errors in the text file. If you wish to overwrite the file with the second method use > instead of >>.

need to output BitLocker status to txt file

I have a simple PowerShell script to check the status of BitLocker drive encryption on a computer on the network. I'd like for the script to determine the status of multiple computers in a text file.
Here's my basic script so far that Nathan Rice had helped with:
$TextFilePath = Read-Host "What is the path to the text file?"
If (Test-Path $TextFilePath) {
$ComputersArray = Get-Content $TextFilePath
ForEach ($Computer in $ComputersArray) {
If (Test-Connection $Computer -Count 1) {
$ComputerStatus = manage-bde -status -cn "$Computer"
Write-Host($ComputerStatus)
} Else {
Write-Host("$Computer appears to be offline.")
}
}
} Else {
Write-Error "The text file was not found, check the path."
}
I modified the code but it only writes one result to the text file, meaning if I have 5 computers in the list, it writes only the results for the first computer:
$TextFilePath = Read-Host "What is the path to the text file?"
If (Test-Path $TextFilePath){
$ComputersArray = Get-Content $TextFilePath
ForEach ($Computer in $ComputersArray) {
If (Test-Connection $Computer -Count 1) {
$ComputerStatus = manage-bde -status -cn "$Computer" |
Out-File -filepath "c:\users\enduser\Bitlocker-Status.txt"
} Else {
Write-Host("$Computer appears to be offline.")
}
}
} Else {
Write-Error "The text file was not found, check the path."
}
I'd like it to write the results for each device to the list.
Create a collection of results. After the loop, write the collection to a file.
$TextFilePath = Read-Host "What is the path to the text file?"
If (Test-Path $TextFilePath){
$ComputersArray = Get-Content $TextFilePath
$ComputerStatusCol = #()
ForEach ($Computer in $ComputersArray) {
If (Test-Connection $Computer -Count 1){
$ComputerStatus = manage-bde -status -cn "$Computer"
$ComputerStatusCol += $ComputerStatus
} Else {
Write-Host("$Computer appears to be offline.")
}
}
$ComputerStatusCol | Out-File -filepath "c:\users\enduser\Bitlocker-Status.txt"
} Else {
Write-Error "The text file was not found, check the path."
}
You need to add the parameter -Append to the Out-File, so that your output is appended to the existing content instead of replacing it:
$ComputerStatus = manage-bde -status -cn "$Computer" |
Out-File -filepath "c:\users\enduser\Bitlocker-Status.txt" -append -force
Easy batch file for admins who want a nice easy file to look through. Just set this up at one of my clients AD Networks, worked like a charm:
Setup a .cdm file, dump it into the netlogon folder
script:
echo Computer:%ComputerName% with username:%username% - Bitlocker check of drive C: >> "\server\share\folder\BitlockerCheck.log"manage-bde -status c: >> "\server\share\folder\BitlockerCheck\BitlockerCheck.log"
Make sure everyone has access to share path (domain users)Edit Group Policy for the container you want it to run in (default domain policy should never be touched, if you want everyone, make a new policy at the top and name it Bitcloker status check).
Go to User Configuration - Policies - Windows Settings - Scripts Right-click Logon, properties, Add - browse to \dcname\netlogon\filename.cmdclick OK, after about 15 minutes (without a forced gpupdate) the file will start populating as users logon/logoff.
On Non-BitLocker computers, it will show the computer name and user with no info.May be cumbersome on very large networks, but you could break out Gp script by OU and separate files as most large companies don't have everyone in one container.

check processor architecture and proceed with if statement

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
}

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
}