Powershell start transcript error - windows

I am running a powershell script from a batch file:
try {
Start-Transcript -path ("C:\PS\Logs\XXXX_Session_QA_" + (Get-Date).tostring("yyyyMMdd-hhmmss-tt") + ".txt")
<Rest of the Code>
}
catch {
stop-transcript
}
Every time I run the script, I see the error
Error: Transcription has not been started. Use the start-transcript command to start transcription.
I have gone through some or most of the previous posts and the code should work but it isn't triggering at all. The initial log file isn't being created either. Any idea why this could be happening or any help here?

Does the folder structure exist for where you are trying to write the transcript to? According to the documentation, it is required (see italics below):
-Path
Specifies a location for the transcript file. Enter a path to a .txt
file. Wildcards are not permitted. If you do not specify a path,
Start-Transcript uses the path in the value of the $Transcript global
variable. If you have not created this variable, Start-Transcript
stores the transcripts in the $Home\My Documents directory as
\PowerShell_transcript..txt files.
If any of the directories in the path do not exist, the command fails.
https://technet.microsoft.com/library/05b8f72c-ae3b-45d5-95e0-86aa1ca1908a(v=wps.630).aspx
You will also need permission to write to that path of course.
So... if the Start-Transcript cmdlet is throwing an error, you are then catching it in the catch{} block (invisibly) which then executes the Stop-Transcript.
This presumably is what is actually causing the error message: the net result is that you are trying to stop transcription when it never started in the first place.

Related

Check if a script has run atleast once before

Is there a way to see if any PowerShell script has executed at-least once before, without the script itself creating any logs? I.e. is there some sort of a native record keeping mechanism for already executed scripts (an example would be an event generating and hence creating an event log), meaning a log of the script actually executed was made at runtime but externally?
For example : If script A was executed once today, check during the second execution (say 2 days later) of script A if it had already executed before.
Can this be done through any Event logs, or through environment variables?
EDIT: Please note, for this particular script, no text files or logs can be made. Is there a way to do this without actually leaving a trace "physically" but instead relying on any parameters being set when a script executes?
EDIT2: This script would be executing with the least of privileges, so not only an account which does not have admin permissions, but would also not have approved permissions to create text or log files.
How about self-modifying code? It's technically cheating, as the change is being done in the script file itself. No external logging is done, though.
write-host -nonewline "Script has started"
$src = get-content $MyInvocation.MyCommand
$header = $src[0]
if($header -notmatch "^#") {
write-host " ...first time!"
$newScript = #()
$newScript += "#"
$newScript += $src
set-content $MyInvocation.MyCommand $newScript
} else { write-host " ...nth time!" }
The script reads its own contents. If the first line doesn't start with a hash, it's the first invokation. The script then creates a new set of source code. The first line is a hash, original source comes after that. Then the original script is overwritten.
As a side note, the requirement to log-but-not-log is self-contradictory just as #Mathias R. Jessen pointed out. There is, however, process tracking audit available in Windows. Also, there is script block logging. In theory (and with proper permissions), one might search the Windows' event logs for previous run attempts.
I'd much rather pop the why stack and find out the underlying reason, as the requirement to eat and keep a cacke sounds very much like an XY problem.

%~dp0 equivalent in powershell (using Expand-Archive cmdlet)

I'm pretty new to scripting (especially powershell) and new to Stack Overflow, so please, excuse my ignorance and please bear with me! I will do my best to specifically explain what I'm looking to do and hopefully someone can give a detailed response of what I could do to make it work..
Intended Process/Work Flow: A co-worker downloads "Install.zip" file that has all the necessary files. This "Install.zip" file contains "Setup.bat" file (for computer config), "Fubar.zip" file, 2 powershell scripts, and a custom powerplan (.pow) file. Once downloaded they will run the "Setup.bat" file and it will pretty much do all the work. Inside that batch file it calls 2 powershell scripts. 1)"Download.ps1" - Downloads some other files from the web. 2.) "Unzip.ps1" - Unzips "Fubar.zip" and places contents in another folder - C:\TEST\
Issue: I've recently gotten familiar with using %~dp0 in batch files. I want to make sure that the location where my co-worker initially downloads the Install.zip doesn't throw off my batch file. So for example.. some people will download .zip files to the "Downloads" folder, then extract contents to proper destination. Others will download the .zip to a specific folder, then extract it within that folder. [Ex: C:\Alex\Install.zip --Extraction-- C:\Alex\Install\((Content))] So I tried to not pre-define file locations due to the variables. I've gotten the %~dp0 to work everywhere I need it to in my batch file. The only issue I have is getting my powershell scripts to use same working directory that my batch file is in. *My batch file and my powershell scripts will always be in the same directory. (Wherever that may be)
Goal: I want my powershell script ("Unzip.ps1") to look for my "Fubar.zip" file in the same directory that its currently running in. (Again - Wherever that may be) I basically want to remove any variables that may throw off the powershell script. I want it to always use it's current working directory to locate Fubar.zip. I basically need powershell to either use its current working directory OR figure out a way to have it pull its current working directory and use that to look for "Fubar.zip".
my current "Unzip.ps1" powershell script is extremely basic.
Unzip.ps1:Expand-Archive -Force c:\ALEX\Install.zip\Fubar.zip -dest c:\TEST\
Batch File Command that calls the Unzip.ps1 script: Powershell.exe -executionpolicy remotesigned -File %~dp0UNZIP.ps1
Please keep in mind, I'm just learning scripting and I'm teaching myself. My knowledge is limited, but I've made it this far and this is the only part I'm stuck on. Please give clear responses. Any help or advice would be extremely appreciated! Using PowerShell 5.0
Thanks in advance!
The equivalent of cmd.exe's %dp0 in PowerShell v3+ is $PSScriptRoot:
Both constructs expand to the absolute path of the folder containing the batch file / PowerShell script at hand.
(The only difference is that %dp0 contains a trailing \, unlike $PSScriptRoot).
Thus, to make your Unzip.ps1 script reference Fubar.zip in the same folder that the script itself is located in, use:
Expand-Archive -Force $PSScriptRoot\Fubar.zip -dest c:\TEST\
Constructing the path as $PSScriptRoot\Fubar.zip - i.e., blindly joining the variable value and the filename with \ - is a pragmatic shortcut for what is more properly expressed as (Join-Path $PSScriptRoot Fubar.zip). It is safe to use in this case, but see the comments for a discussion about when Join-Path should be used.
The automatic $PSScriptRoot variable requires PS v3+; in v2-, use
Expand-Archive -Force ((Split-Path $MyInvocation.Mycommand.Path) + '\Fubar.zip') -dest c:\TEST\
From your description, I gather that Fubar.zip and Unzip.ps1 are in the same directory. We'll pretend this directory is C:\Users\Me\Temp; although I understand that may vary.
Powershell's working directory will be the directory you're in (if called from CMD) when you launch; otherwise, it'll be from $env:UserProfile. Since the .bat file always call Unzip.ps1 from the directory that it's in (C:\Users\Me\Temp), powershell.exe will find it with this command (you can still use %~dp0 here; it's not hurting anything):
powershell.exe -ExecutionPolicy RemoteSigned -File Unzip.ps1
Inside of Unzip.ps1, you'll use Get-Location:
Expand-Archive -Force "$(Get-Location)\Fubar.zip" -dest c:\TEST\
However, if the .bat file does a cd into another directory, this won't work. From your %~dp0UNZIP.ps1 example, I assume this isn't the case, but let's address it anyway. If this is the case, you need to process from where the location of the script is. So for this call the full/relational path to the .ps1:
powershell.exe -ExecutionPolicy RemoteSigned -File C:\Users\Me\Temp\Unzip.ps1
Then, your Unzip.ps1 will need to look like this:
Expand-Archive -Force "${PSScriptRoot}\Fubar.zip" -dest 'C:\TEST\'
Alternatively, you can also do some fancy path splitting, as #JosefZ suggested. The $PSCommandPath and $MyInvocation variables contain the full path to your script; which you should familiarize yourself with:
$location = Split-Path $PSCommandPath -Parent
$location = Split-Path $MyInvocation.MyCommand.Path -Parent
Expand-Archive -Force "${location}\Fubar.zip" -dest 'C:\TEST\'
Note: Of course, you wouldn't set $location twice. I'm just showing you two ways to set it.
I hope this helps!
Prior to Powershell 3
$currentScriptPath = Split-Path ((Get-Variable MyInvocation -Scope 0).Value).MyCommand.Path
Otherwise, $PsScriptRoot will work. If you're going to depend on it, though, I'd make sure you mark the script with #Requires -version 3
I'd advise against changing the PWD unless you must. Which is to say, reference the variable directly.

Problems Executing Powershell from .cmd file

I am attempting to run a build task from a .cmd file where Powershell extracts a zip file, which helps bypass a problem with Visual Studio's limit on the number of directory characters. However, I am having problems getting the Powershell command to execute correctly. I've tried a number of variations with the quotations, and I either get a termination error, or the Powershell command outputs as a string with the zip file not extracted. Below is an example of my current .cmd file:
//%1% is a passed in command line argument for the absolute path, e.g. C:\path\to\dir
set Source=%1%directory.zip
set Destination=%1%directory
powershell -Command $pscmd = '{Add-Type -assembly "system.io.compression.filesystem";[io.compression.zipfile]::ExtractToDirectory("%Source%", "%Destination%");}'; Write-Host $pscmd;
I'm very open to a number of variations that can get this to work, provided that this task runs on the command line, uses Powershell, and can be executed from a .cmd file, which is triggered by our app's build process. I'll be happy to provide additional information if needed. Thanks!
This was a strange one. Your code above has some sort of hidden character in it. I took the code and opened it in notepad, saved as ANSI, and when you type it to command line or open it again in a new instance of notepad you can see the error.
Neither add-type nor ExtractToDirectory give output, so I removed your pscmd var.
I would open your existing script, save as ansi as a new file name, delete the original, rename the new one back to the original name.
Here is what I came up with to troubleshoot your script, and it works on my machine.
I named my script L:\util\unzip.cmd
setlocal
//%1% is a passed in command line argument for the absolute path, e.g. C:\path\to\dir
set _Source='%1\directory.zip'
set _Destination='%1\directory'
echo _Source=%_Source%
echo _Destination=%_Destination%
set _c1=Add-Type -assembly system.io.compression.filesystem;
set _c2=[io.compression.zipfile]::ExtractToDirectory(%_Source%, %_Destination%)
echo _c1=%_c1%
echo _c2=%_c2%
set _Command=^& {%_c1% %_c2%};
: to echo, use double quotes or cmd thinks text after & is another command
echo _Command="%_Command%"
pause
powershell -Command "%_Command%"
endlocal
I ran it like this, and it worked: unzip.cmd L:\util
I'll bet this this info, you are good to go.

UnauthorizedAccessException from PowerShell when using Invoke-WebRequest

I know that the error is pretty much self-explenatory but yet I am not able to find solution. I write a PowerShell script to automate the set-up project for the dev machines. There are a set of programs that must be installed so what I want to do i first download the file and then install it. I am having problems with downloading file from the web to the local machine.
My logic is as follows. I have an .xml file where I configure all the stuff. For the downloads it looks like this:
<download source="https://github.com/msysgit/msysgit/releases/download/Git-1.9.5-preview20150319/Git-1.9.5-preview20150319.exe"
destination="C:\Temp" filename="Git-1.9.5-preview20150319.exe"/>
Then in my PowerShell script file I have this function:
function install-tools() {
Set-ExecutionPolicy RemoteSigned
$xmlFileInformation = $config.SelectNodes("/setup/downloads/download");
Foreach ($file in $xmlFileInformation)
{
$("Filename: " + $file.filename)
$("File source: " + $file.source)
$("File destionation: " + $file.destination)
$("****************************************************************");
$("*** Downlading "+ $file.filename);
$("****************************************************************");
Invoke-WebRequest $file.source -OutFile $file.destination
}
$("Task finished");
}
After executin I get the error from the title UnauthorizedAccessException from PowerShell when using Invoke-WebRequest. Two things that I can mention is that I have included Set-ExecutionPolicy RemoteSigned and also, I execute the script running PowerShell as administrator. I've tried different paths but it's the same everytime, I don't get permission to write anywhere. The only thing that I can't try is using another drive I have only one - C:\.
And one strange thing - my destination directory is C:\Temp but during one of my attempts I didn't have such a directory in C:\ so I ended up with file named Temp in my C:\ but this was the closest I get to getting a file.
I don't need to save those files in a particular place since it's very possible to delete the entire directory after successfull set-up so what I need is a way to let powershell save files somewhere in my C:\ drive. Since I'm not sure if this is related with administrating my system and setting the correct rights (I tried to lower the protection as much as I can) or I miss something in my PowerShell script?
You does not specify file name to download to. Replace
-OutFile $file.destination
to
-OutFile (Join-Path $file.destination $file.filename)

How can I find a Powershell's running directory in a GPO?

I have a powershell script that runs in a GPO. It needs to open a text file, also inside that GPO. I can't get the path information for the text file because the script doesn't execute in the same directory the script is.
I need to open the text file somehow. How do I do it?
I can't fully understand what you're trying to do, but if I've guessed right then you want the path of the script while its been executed?
If that's the case then use this variable:
$MyInvocation.MyCommand.Path

Resources