0

Update2:

Now, when I know, that x32 is the problem I debugged into the script using powershell_ise_x32 and found out, that $Word.Documents is null. So Powershell-API for Word has a different behaviour in x32 PowerShell, then in 64bit.

enter image description here


Update:

The error occurs, when using PowerShell x32 and occurs NOT on PowerShell 64bit. That was really it. Powershell x32 was executed because I started it from the Total Commander 32bit.

The question is now - why 32bit and 64bit PowerShell have different behaviour?


Initial Question:

I wrote a powershell script, to convert my WordDocuments and merge them to one.
I wrote a Batch script, to start this powershell script.

When I execute the script directly in "Powershell ISE" the script works fine.

When I execute the batch script as Administrator via context menu, the script reports errors. In this case the C:\WINDOWS\SysWOW64\cmd.exe is executed.

When I execute another cmd.exe found on my system as Administrator - everything works fine: "C:\Windows\WinSxS\amd64_microsoft-windows-commandprompt_31bf3856ad364e35_10.0.15063.0_none_9c209ff6532b42d7\cmd.exe"

Why do I have different behaviour in different cmd.exe? What are those different cmd.exe?

enter image description here

enter image description here

enter image description here


Batch Script:

cd /d "%~dp0"

powershell.exe -noprofile -executionpolicy bypass -file "%~dp0%DocxToPdf.ps1" 
pause

Powershell Script

$FilePath = $PSScriptRoot
$Pdfsam = "D:\Programme\PDFsam\bin\run-console.bat"




$Files = Get-ChildItem "$FilePath\*.docx"
$Word = New-Object -ComObject Word.Application
if(-not $?){
    throw "Failed to open Word"
}

# Convert all docx files to pdf
Foreach ($File in $Files) {
    Write-Host "Word Object: "  $Word
    Write-Host "File Object: "  $Word $File
    Write-Host "FullName prop:" $File.FullName

    # open a Word document, filename from the directory
    $Doc = $Word.Documents.Open($File.FullName)

    # Swap out DOCX with PDF in the Filename
    $Name=($Doc.FullName).Replace("docx","pdf")

    # Save this File as a PDF in Word 2010/2013
    $Doc.SaveAs([ref] $Name, [ref] 17)
    $Doc.Close()
}

# check errors
if(-not $?){
    Write-Host("Stop because an error occurred")
    pause
    exit 0
}

# wait until the conversion is done
Start-Sleep -s 15


# Now concat all pdfs to one single pdf
$Files = Get-ChildItem "$FilePath\*.pdf" | Sort-Object

Write-Host $Files.Count

if ($Files.Count -gt 0) {

    $command = "" 
    Foreach ($File in $Files) {
        $command += " -f "
        $command += "`"" + $File.FullName + "`""
    }

    $command += " -o `"$FilePath\Letter of application.pdf`" -overwrite concat"
    $command = $Pdfsam + $command
    echo $command

    $path = Split-Path -Path $Pdfsam -Parent 
    cd $path

    cmd /c $command

}else{
    Write-Host "No PDFs found for concatenation"
}




Write-Host -NoNewLine "Press any key to continue...";
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");
Skip
  • 6,240
  • 11
  • 67
  • 117
  • 2
    Read the Microsoft article about [File System Redirector](https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187.aspx) and other WoW64 pages. 32-bit `cmd.exe` in directory `%SystemRoot%\Syswow64` is started when the application starting it is a 32-bit application. In 32-bit applications `%SystemRoot%\Sysnative\cmd.exe` can be executed to start 64-bit `cmd.exe` on 64-bit Windows. See also answer on ['Run As Administrator' Changes Batch File Current Directory (Sometimes)](https://stackoverflow.com/a/31655249/3074564). – Mofi Aug 05 '17 at 15:09
  • Sorry, but how is it related to my question, that 32 and 64 bit versions of cmd exist? And changing directories is fixed by `cd /d "%~dp0" ` in my batch script – Skip Aug 05 '17 at 15:17
  • 1
    There should be two cmd.exe files in the WinSxS directory, both of which are hard linked to their normal locations, the 64-bit build in System32 and the 32-bit build in SysWOW64. Never use files directly from the system's WinSxS directory. – Eryk Sun Aug 06 '17 at 02:09
  • If you're having a problem with the PowerShell script using 32-bit powershell.exe, I suggest you do as @Mofi suggested. Try running the 64-bit version explicitly from 32-bit CMD: `C:\Windows\SysNative\WindowsPowerShell\v1.0\powershell.exe`. This path will *only work* in 32-bit CMD. The virtual "SysNative" directory doesn't exist for 64-bit applications, which is an unfortunate and annoying oversight in my opinion. – Eryk Sun Aug 06 '17 at 02:19
  • 1
    Also, figure out why running a batch script from Explorer is using 32-bit CMD. Something is either misconfigured in the .bat file association or maybe you're using 32-bit Explorer. – Eryk Sun Aug 06 '17 at 02:27
  • The error occurs, when using PowerShell x32 and occurs NOT on PowerShell 64bit. That was really it. Powershell x32 was executed because I started it from the Total Commander 32bit. The question is not - why 32bit and 64bit PowerShell have different behaviour? – Skip Aug 06 '17 at 10:48

2 Answers2

0

I've found $PSScriptRoot to be unreliable.

$FilePath = $PSScriptRoot;
$CurLocation = Get-Location;
$ScriptLocation = Split-Path $MyInvocation.MyCommand.Path

Write-Host "FilePath = [$FilePath]";
Write-Host "CurLocation = [$CurLocation]";
Write-Host "ScriptLocation = [$ScriptLocation]";

Results:

O:\Data>powershell ..\Script\t.ps1
FilePath = []
CurLocation = [O:\Data]
ScriptLocation = [O:\Script]

As to the differences between the various cmd.exe implementations, I can't really answer that. I should have thought they'd be functionally identical, but maybe there's 32/64-bit differences that matter.

0

The error occurs, when using PowerShell x32 and occurs NOT on PowerShell 64bit.

I debugged into the script using powershell_ise_x32 and found out, that $Word.Documents is null.

This is because on my system Word 64bit is installed.

Skip
  • 6,240
  • 11
  • 67
  • 117
  • Does `$Word = New-Object -ComObject Word.Application` succeed? If not, maybe it's an in-process COM component that's only available in a 64-bit DLL. – Eryk Sun Aug 06 '17 at 13:06
  • It succeeds. Look at the screnshot, $Word is not null – Skip Aug 06 '17 at 15:10