TFS post build powershell script not seeing commands from imported module - powershell

We have a TFS build process using a custom template. The build works fine with the crm solution files successfully being created. We are then attempting to run a powershell script on the post build. This script imports a module. But the commands in the module are not being exposed. Whenever we attempt to invoke a command, we get an error. Along the lines of
The term 'Get-XrmSolution' is not recognized as the name of a cmdlet,
function, script file, or operable program.
It doesn't matter which command we use in that module, we get the same kind of error.
To troubleshoot, we have logged onto the build server under the identity of the build account and can successfully run the script we are attempting to run.
Putting some more output into the script to troubleshoot...
Get-Module lists Xrm.Framework.CI.PowerShell. - Good.
Get-Command -Module "Xrm.Framework.CI.PowerShell" returns nothing. From the console, a number of commands are listed.
Is there something we need to do with the running of powershell post build scripts to enable the contents of an imported module to be seen?

Watch out for the bitness of PowerShell invoked by MSBuild and likewise, the bitness of MSBuild launched by Visual Studio. Certain modules only run in either 32-bit or 64-bit PowerShell and not both. You want to make sure the correct version of PowerShell is getting launched.

IIRC you have to explicitly import the module with no assumption of being loaded on user profile, nor on the script path.
Suppose Module1.psm1 is in the same folder as your script, use something like
Import-Module (Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Definition) 'Module1.psm1')

I had the same problem.
The module was loaded in the 'C:\Program Files\WindowsPowerShell\Modules' folder (64 bits).
It all seemed fine when I logged on as the user, but it failed during TFS build.
Solution: I had to uninstall the module in PowerShell 64 bit and re-install in PowerShell 32 bit.
The module was then installed in 'C:\Program Files (x86)\WindowsPowerShell\Modules' folder.

Related

Can I run powershell commands without installing module?

I would like to run a script that requires to use commands from the GroupPolicy module. However, this module is not guaranteed to be installed on every machine and some machines might be stand alone. Can I have have the module copied over with my scripts and run commands from it, without installing the module?
Can I have have the module copied over with my scripts and run commands from it, without installing the module?
Yes. Installing a module in PowerShell simply means placing it one of the directories listed in the $env:PSModulePath environment variable, which allows PowerShell to discover it and import (load) it on demand, as part of the module auto-loading feature
However, you're free to copy modules elsewhere, as long as the code that relies on them knows their path and loads them with an explicit Import-Module call.
For instance, if you bundle your script with a GroupPolicy subdirectory containing that module, the script could import it as follows:
# $PSScriptRoot contains the calling script's directory.
Import-Module $PSScriptRoot\GroupPolicy

imported powershell module not visible when running via ssis package

I installed the ImportExcel module as described here:
https://www.powershellgallery.com/packages/ImportExcel/5.0.1
Then I wrote a simple ps1 file that loops though certain folder and converts each xlsx file in that folder to csv format (using ConvertFrom-ExcelSheet method from the above module).
Finally, I wrapped that ps1 script into a .bat file.
That batch script works fine when executed manually via windows command line.
However, when the same batch file is executed from an SSIS package (on the same computer, under my credentials, using the standard Execute Process Task ), when the powershell script reaches the line calling ConvertFrom-ExcelSheet method, I am getting the following error:
The term 'ConvertFrom-ExcelSheet' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
The PC was restarted after module installation.
The module was installed with the AllUsers scope.
Elevated shell during module installation.
Any hints what I can do to get this module working in SSIS? Or at least, where to start looking?
Environment:
PowerShell 5.0.10586.117
Windows 7 Enterprise x64
Visual Studio 2012
Problem solved by moving the installed module to user's module folder i.e. %USERPROFILE%\Documents\WindowsPowerShell\Modules
There is still no clear explanation why the module was not working from shared modules folder but at least the issue is now gone.

PowerShell Module cannot be loaded when running Pester test in Visual Studio

I have created a PowerShell test script, Common.tests.ps1, using Pester against some functions in a PowerShell script, Common.ps1, in the same directory.
There is a TestInitializer.ps1 script, also in the same directory, which uses the Microsoft.Xrm.Data.PowerShell module to create and get records in a Dynamics CRM instance.
When running the PowerShell test script from Visual Studio, the test fails in the Test Explorer with a message:
CommandNotFoundException: The module 'Microsoft.Xrm.Data.PowerShell' could not be loaded. For more information, run 'Import-Module Microsoft.Xrm.Data.PowerShell'.
The same test when run from the PowerShell ISE, however, runs without issue. This would seem to be as if the module is not installed for the instance as run by Visual Studio (I confirmed this when running Get-Module -ListAvailable and seeing that the output did not include the Microsoft.Xrm.Data.PowerShell module for the Visual Studio test), though even explicit calls like Import-Module Microsoft.Xrm.Data.PowerShell -Global -Force don't seem to load the module during the script execution with Visual Studio.
Here's Common.test.ps1:
$here = (Split-Path -Parent $MyInvocation.MyCommand.Path)
. $here\Common.ps1
. $here\TestInitializer.ps1
Describe "SelectionToSingleCharString" {
Context "StringTransforms" {
It "Retrieves a CRM record and uses the optionset value to retrieve a single character" {
SelectionToSingleCharString($crmRecord.new_type) | Should Be "I"
}
}
}
Snippet from TestInitializer.ps1:
# Whether or not this is uncommented does not matter
#Import-Module "$env:SystemRoot\System32\WindowsPowerShell\v1.0\Modules\Microsoft.Xrm.Data.PowerShell\Microsoft.Xrm.Data.PowerShell.psd1" -Global -Force
#$modules = Get-Module -ListAvailable
#Write-Host $modules
# Failing here
Microsoft.Xrm.Data.PowerShell\Connect-CrmOnPremDiscovery -ServerUrl $loginServerUrl -OrganizationName $loginOrgName -Credential $cred
I may instead design the test to use Mock instead of actually attempting to create/read records, though not being able to load external modules and run in Visual Studio would be limiting.
Regarding module install directories (skip this if you are interested in the actual problem):
First you should never install modules to $PSHome\Modules (%Windir%\System32\WindowsPowerShell\v1.0\Modules). This folder is reserved for modules shipped with Windows only.
You should always install your modules used only by your user under the following path:
$Home\Documents\WindowsPowerShell\Modules
And for a system-wide installation under:
$Env:ProgramFiles\WindowsPowerShell\Modules
Further reading regarding installing modules in PowerShell can be found on MSDN.
Regarding your actual problem:
What Visual Studio Version are you using? I have Visual Studio 2017 Community edition installed and can not reproduce your error. My PowerShell is also running as a 64-bit process. Your PowerShell could be running as a 32-bit process. For the 32-bit PowerShell the module directories are different. This would explain why the module you installed isn't showing up in Visual Studio.
You can verify if your PowerShell is running in a 64-bit process with the following command:
PS> [Environment]::Is64BitProcess
True
To make your modules accessible for the 32-bit PowerShell you need to install them under the following path as well:
{$Env:ProgramFiles(x86)}\WindowsPowerShell\Modules

TFS vNext Powershell build step is using older version of Powershell module

a build with Powershell++ (it comes from Extension Utilities Pack) step keeps failing when I try to run task containing following code Copy-Item -FromSession $cs to copy items from different machine. The error message is
A parameter cannot be found that matches parameter name 'FromSession'.
However, the code does not fail when run from PS console when I'm logged to that machine.
Then I included
(get-command copy-item).Version.ToString()
(get-command copy-item).ModuleName.ToString()
And got version 3.1.0.0 and module Microsoft.PowerShell.Management in PS console and 3.0.0.0 in TFS build step output (module is the same). The version of Powershell is identical in both - 5.0.10586.117.
Looks like the Powershell that is running inside TFS is using different modules.
Can anybody help? Thanks.
Shame on me for not knowing enough about Powershell providers. When wildcard was included in the source path I got this error, without the wildcard it worked fine.
The FromSession parameter is available in PS v5 and not limited to Microsoft.PowerShell.Management 3.0.0.0 (but that is still a mystery to me).

Can my PowerGUI compiled PowerShell script be viewed by users?

I use PowerGUI to convert my PowerShell scripts to executables, and it is working fine.
I'd like to prevent my compiled script from being extracted or decompiled by users I distribute the generated executable to.
Is it possible to view my PowerShell script inside the generated executable? If so, how do I prevent this?
Unfortunately with PowerGUI it's not possible to prevent users of your executable from viewing your script, even if you use the "Protect script source code with a password" option.
The executable that PowerGUI generates is a self extracting ZIP file so it's possible to use 7-zip or WinRAR to open this file and view the original PowerShell script.
If you set a password using the "Protect script source code with a password" option all this does is password protect the files inside the ZIP container. However when launching the generated executable you'll be prompted for said password which can then be used to access the original script.
If you want to somewhat obfuscate the code, look at PS2EXE:
http://ps2exe.codeplex.com/
which points to:
https://gallery.technet.microsoft.com/PS2EXE-Convert-PowerShell-9e4e07f1
download the ps2exe
http://ps2exe.codeplex.com/
run power shell
cd the folder of ps2exe
run:
.\yourfile.ps1 -inputFile C:\Users\franc\Desktop\temp\ps2exe\Install.ps1 C:\Users\franc\Desktop\temp\ps2exe\Install.exe
check the folder, the exe will be there