I am using Microsoft PowerShell v4:
PS C:\> get-host
Name : ConsoleHost
Version : 4.0
InstanceId : 3b4b6b8d-70ec-46dd-942a-bfecf5fb6f31
UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : de-CH
CurrentUICulture : en-US
PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace : System.Management.Automation.Runspaces.LocalRunspace
I have developed a C# project in Visual Studio 2012 targeting .NET Framework 4 which contains some Cmdlet and the Snapin. I can debug them and everything works just fine.
I've created the path C:\PowerShell\Modules\ and added it to the PSModulePath environment variable.
I put the rMySnapIn.dll to the path C:\PowerShell\Modules\MySnapIn.
I would expect that the module is automatically loaded so I have my new cmdlets ready to use, but they're not: the module is not loaded. I have to write Import-Module MySnapin in order to get it loaded.
How can I get the module automatically loaded?
A checklist that may help you identify the issue:
According to What's New in Windows PowerShell, "Automatic importing of modules is triggered by (a) using the cmdlet in a command, (b) running Get-Command for a cmdlet without wildcards, or (C) running Get-Help for a cmdlet without wildcards." (That applies to V3 and V4.) How did you confirm the module was not loaded?
According to about_Modules, "Only modules that are stored in the location specified by the PSModulePath environment variable are automatically imported." You stated that you did add your path to PSModulePath. When I examine mine, I see that each path included is terminated with a backslash, so in your case you would need C:\PowerShell\Modules\ rather than just C:\PowerShell\Modules. What is the value of your $env:PsModulePath ?
According to this post from Thomas Lee as well as my own experience, autoloading does not work with script modules; however, you state you are using a compiled module, so this should not be your issue.
The $PSModuleAutoLoadingPreference preference variable can be used to turn off autoloading; however, unless you have explicitly changed it, it defaults to All so likely that is not the problem (about_Preference_Variables shows you the possible values). What is your value of $PSModuleAutoLoadingPreference ?
Last but not least--I am particularly suspicious over the fact that you seem to be mixing snapins and modules. They are distinct types of entities, and are not designed to be mixed. Snapins are loaded via Add-PSSnapin. Modules are loaded via Import-Module. And modules, as you know, are also loaded by auto-loading--I suspect that may not be true of code written as a snapin. Furthermore, snapins are deprecated; new code should be written using modules (that is, derive from Cmdlet or PSCmdlet, as detailed in Writing a Windows PowerShell Cmdlet).
If you want to load it automatically you can add the Import-Module MySnapin command line to your PowerShell profile.
To find out the location of your PowerShell profile just type $profile in a PowerShell and by default the profile path is:
C:\Documents and Settings\User\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
If the Microsoft.PowerShell_profile.ps1 file does not exist just create it.
I noticed that following structure is not supported by PowerShell 4:
Modules\MySnapIn\1.0.0\MySnapIn.psm1
Works fine after update to version 5.
Note: I'm authoring only script modules, so I may be wrong.
PowerShell module autoload depends on command discovery. I suspect that if you create manifest (New-ModuleManifest) and name commands that your binary module exposes, autoloading should kick-in and load module if someone will try to use one of these commands:
New-ModuleManifest -Path MySnappin.psd1 -RootModule MySnappin.dll -CmdletsToExport Get-Foo, Set-Bar
Related
First I would like to say thank you for helping me with this issue. I really appreciate your time and efforts.
The title sums it up pretty well however I will provide a few specifics. Basically if I pull my OS version using C# it returns the result 6.2 which is for Windows 8 even though my system is 8.1 which should return 6.3. After my research I found that this was a documented limitation inside of the System.Enviroment class, ... gotta love those "features".
I have found a way to deal with this by going into the reg and comparing my 6.2 result with the current version key under HKLM\SOFTWARE\Microsoft\WindowsNT\CurrentVersion however, this is a very risky operation as the reg info could change without notice.
It all got screwy on me when I tried to poll WMI though Powershell. I can't remember why I did a WMI search though Powershell, I guess its not just cats that get curious :)
C# Code:
string version = Environment.OSVersion.ToString();
MessageBox.Show(version);
//Output "Microsoft Windows NT 6.2.9200.0"
Powershell Code:
[System.Environment]::OSVersion | Select-Object -Property VersionString
//OUtput "Microsoft Windows NT 6.3.9600.0"
I have tried both x86 and x64 builds of my C# program as well as running the Powershell both x86 and x64. The discrepancies did not change.
This raises several questions for me but the basic one is where does Powershell get the correct info from? Does Powershell use the reg like I had planned to fix its output? Since my build targets .Net 3.5 does Powershell pull .Net 4.5 (changed my build and this changed nothing).
From my understanding [System.Environment]::OSVersion pulls info the same as System.Environment.OSVersion.
How the heck does Powershell work and C# fails??
:)
Thanks again!
As far as I can tell only the Environment.Version call in a C# program is incorrect (6.2). In PowerShell it is correct (6.3). In WMI called via PowerShell or C# it is correct. In fact, C# compiled from source in PowerShell using Add-Type returns 6.3.
Looking into the article here (thanks Booga Roo) it indicates that unless your application specifically says it targets Windows 8.1 via a manifest file, you get the old version (6.2).
You can make a C# application return the correct version by adding an application manifest file and declaring 8.1 support by uncommenting the line
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
It seems safe to assume that the writers of PowerShell at Microsoft included an application manifest with powershell.exe that declares Windows 8.1 support.
From C# code I'm trying to retrieve all the namespaces from powershell... (Later more complex things, like creating namespaces)
PowerShell ps = PowerShell.Create();
ps.AddCommand("Import-Module").AddArgument("ServiceBus").Invoke();
var result = ps.AddCommand("Get-SBNamespace").Invoke();
Above code gives the following exception:
The 'Get-SBNamespace' command was found in the module 'ServiceBus',
but the module could not be loaded. For more information, run
'Import-Module ServiceBus'.
Does anyone know how to solve this error?
CURRENT STATUS: after some debugging I've found that no modules are loaded by default in the PowerShell object. Using the code:
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ImportPSModule(new string[]{#"serviceBus"});
PowerShell ps = PowerShell.Create(iss);
doesn't work to load the service bus module. Also the code:
ps.AddCommand("Import-Module").AddParameter("-Name", "serviceBus").Invoke();
doesn't work to import the service bus module. Running Visual Studio in administrator mode also doesn't make a difference
Thanks in advance
You didn't say which version of Visual Studio you're using. If it's VS 2012, when you tried the x64 platform target did you make sure that "Prefer 32-bit" was not checked? Even if it was not checked try checking it, saving the project configuration, clearing it and saving again - this worked for me on another project.
UPDATE
It's been suggested elsewhere that there's a bug in VS2012 that shows "Prefer 32-bit" as greyed-out and unchecked when it's actually active. I'm running Update 2 and I don't see that. But it sounds like you might be. I suggest you edit the .csproj file directly.
Whilst "Platform Target" is set at "Any CPU", in Solution Explorer, right-click on the Project name (or, with go to the PROJECT menu) and select "Unload Project". Project files will close and Solution Explorer will display project name (unavailable) > The project file was unloaded:
Right-click on the Project name again and select "Edit project name.csproj". The file is XML and mostly comprises PropertyGroup and ItemGroup elements. In a console project, the first PropertyGroup usually contains a Platform element which should read AnyCPU if you followed my instructions above. The next two PropertyGroups are normally for Debug and Release configurations. If you've added another configuration, it will have its own PropertyGroup. In each of these, look for an element which reads:
<Prefer32Bit>true</Prefer32Bit>
What you should have is an element which reads:
<Prefer32Bit>false</Prefer32Bit>
Either change it or insert it (in each configuration ProjectGroup), save the file and close it. Back in Solution Explorer, right-click the project and select "Reload Project". Let me know if that solves it. You can confirm your PowerShell is now running 64-bit by get the result of
[System.IntPtr]::Size
e.g.
ps.AddScript("[System.IntPtr]::Size");
which will be 4 in an x86 process and 8 in an x64 process.
Which my project set up like this, I was able to load ServiceBus using:
ps.AddCommand("Import-Module").AddArgument("ServiceBus");
Hopefully, you will, too.
I don't have ServiceBus installed so I can't verify exactly what you've tried but
ps.AddCommand("Import-Module").AddArgument("ActiveDirectory").Invoke();
worked for me, so your original syntax looks good.
Just to test for failure, I tried:
ps.AddCommand("Import-Module").AddArgument("CheeseDirectory");
ps.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
var importResult = ps.Invoke();
foreach (PSObject result in importResult)
{
Console.WriteLine(result);
}
and got
The specified module 'CheeseDirectory' was not loaded because no valid
module file was found in any module directory.
Have you tried similar?
Do you take care of your Assembly target in your C# program (x86 versus X64). The module may exist in one target, not in the other. PowerShell exists in both.
Seems you're trying to import some modules and execute the cmdlet or function inside the module, right?
So I think you could try the following code:
PowerShell ps = PowerShell.Create();
Assembly ass = Assembly.LoadFile(#"yourServiceBus.dll");
ps.AddCommand("Import-Module").AddParameter("Assembly", ass).Invoke();
var result = ps.AddCommand("Get-SBNamespace").Invoke();
Hope this could help.
Problem!
I have a little python script, which goes throught a web page (http-crawling). This web-page is hosted inside the intranet and uses NTLM authentication to gather access to it.
So, I found this task (retrieve http-content) easily programmable using python, instead of trying to re-write the whole python script to C# and then use it througth "Script Task" on SSIS, in order to complete the task.
Hint!
I've looked up closely to SSIS tools and I found that there is a Control Flow named "Execute Process Task", which lets you to execute Win32 executables.
But the problem resides in how to call my python script since it's not executable and needs to be interpreted by the python interpreter (if you'll forgive the repetition). So, I could easily end up building a simple ".bat" file that calls both the python script and the interpreter. And then execute that file through SSIS "Execute Process Task".
Question!
Is there any other way to implement this? (neat way)
Edit #1
Usage
The information retrieved from the script will be storing that information into a table from a database, So that information will be accessed trough the database table from another SSIS process.
I'm retrieving the information from different sources (flat files, database tables, http request, ...) in order to archive that information into a database that could be posted in a web services and then accessed from a Excel project.
Thanks in Advance!
The easiest, at least to my brain, mechanism for using IronPython from the confines of SSIS would be to invoke the external process and dump to a file and then use that as a source for a dataflow.
That said, I was able to host an IronPython app from C# and use the returned data to populate the output buffers and interact with that data in the pipeline. I've only had one machine to perform this on so I'm listing everything I recall doing until the package went green.
Prerequisites
This article set me down the path of how to make this work. Hosting IronPython in a C# 4.0 program I would strongly urge you to create a C#/VB.NET console app and get your IronPython integration working there first as SSIS is going to add an additional layer to everything.
There may be the ability to host older versions of IronPython within C# without requiring the 4.0 framework but that's far beyond the realm of my competency. What I can say is that to use the 4.0 framework, you are looking at SQL Server 2012. A 2008 package can target up to the 3.5 framework (default is 2.0).
Global Assembly Cache, GAC for short. It is a special place in Windows where signed assemblies can live. SSIS may be able to use assemblies that aren't in the GAC, but I've not had luck doing so. This case was no different. My Console app worked fine but when I copied that code into SSIS, it'd tank with Could not load file or assembly 'Microsoft.Scripting... error messages. Blessedly, IronPython-2.7.2.1 (and probably previous versions) are strongly signed dlls. That means you can and must add them into the GAC.
In your Visual Studio directory, look for the Visual Studio Command Prompt (2010).
Assuming your IronPython installation folder is C:\tmp\IronPython-2.7.2.1\IronPython-2.7.2.1 you would type cd C:\tmp\IronPython-2.7.2.1\IronPython-2.7.2.1 Then I registered the following 3 assemblies
C:\tmp\IronPython-2.7.2.1\IronPython-2.7.2.1>gacutil -if Microsoft.Dynamic.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
C:\tmp\IronPython-2.7.2.1\IronPython-2.7.2.1>gacutil -if IronPython.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
C:\tmp\IronPython-2.7.2.1\IronPython-2.7.2.1>gacutil -if Microsoft.Scripting.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
My SSIS project, I had set the Run64bitRuntime to False but in retesting, it does not matter. The default it True and that seems to work fine.
Python script - I don't have enough of a background to make the integration between C# and .NET DLR languages more graceful. It'd have been nice to supply a string or something containing the script I wanted to execute and perhaps that's what a script block is about but I don't have time to investigate. So, this solution requires a script file sitting out somewhere on disk. I had trouble with the imports working from a hosted script (no module named X exceptions). Undoubtedly there's some magic with class paths and all that stuff that needs to provided to the host to make it work well. That's probably a different SO question btw.
Set up
I have a file sitting at C:\ssisdata\simplePy.py
# could not get a simple import to work from hosted
# works fine from "not hosted"
#import os
def GetIPData():
#os.listdir(r'C:\\')
return range(0,100)
After adding a script task to the Data Flow, I configured it to have a single column on the output buffer (wstr 1000). I then used this as my source code.
using System;
using System.Collections.Generic;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
/// <summary>
/// Attempt to use IP script as a source
/// http://blogs.msdn.com/b/charlie/archive/2009/10/25/hosting-ironpython-in-a-c-4-0-program.aspx
/// </summary>
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
/// <summary>
/// Create data rows and fill those buckets
/// </summary>
public override void CreateNewOutputRows()
{
foreach (var item in this.GetData())
{
Output0Buffer.AddRow();
Output0Buffer.Content = item;
}
}
/// <summary>
/// I've written plenty of code, but I'm quite certain this is some of the ugliest.
/// There certainly must be more graceful means of
/// * feeding your source code to the ironpython run-time than a file
/// * processing the output of the code the method call
/// * sucking less at life
/// </summary>
/// <returns>A list of strings</returns>
public List<string> GetData()
{
List<string> output = null;
var ipy = Python.CreateRuntime();
dynamic test = ipy.UseFile(#"C:\ssisdata\simplePy.py");
output = new List<string>();
var pythonData = test.GetIPData();
foreach (var item in pythonData)
{
output.Add(item.ToString());
}
return output;
}
}
Quick shot of what my references look like
Click the run button and great success
how neat do you want to be? I think you option is fine and you wont find any simpler way to solve your problem. You have a list of files and need to execute them, that's it.
One thing I can think of is adding all the file paths to a sql table and execute them with xp_cmdshell
you need to enable it on the sql instance (I assume you have one since you are considering using SSIS)
EXEC sp_configure 'show advanced options', 1
GO
reconfigure
go
EXEC sp_configure 'xp_cmdshell', 1
GO
reconfigure
go
than you can loop on the table and for each row execute:
exec master.dbo.xp_cmdshell 'your_script'
How about the simple solution (without .bat):
In the Editor for "Execute Process Task" set Exectutable to your Python INTERPRETER
C:\...\Python34\python.exe
for Arguments set your script path first followed by any args for the script
H:\...\test\helloworld.py -a 1 -b 2
don't forget your WorkingDirectory
H:\...\test
I have a site for which i want to activate feature using powershell
When i run the following command :
enable-spfeature FEATURE NAME -url http://URL
it throws an error :value cannot be null parameter name section.
it basically fails to find the configuration section located under the web application configuration.If i create a file with name powershell.exe.config and place it under the
powershell folder ,it works fine but i dont want to touch the system folder.
Is it possible to give powershell a path of config located int some other folder and ask it to use that while activating feature.
I have tried something like this but with no luck
$configpath = "C:\DevTools.exe.config"
[System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE",$configpath)
enable-spfeature Feature name -url http://url
Why arn't you putting the configuration information in the web application web.config file?
#Lee Activating the feature from powershell expects the configuration to be under the hosting process which is powershell in this case.
The solution to my problem was to load the configuration at run time as shown below and using windows powershell instead of using sharepoint management shell :
[System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE",$configpath)
add-type -path C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Configuration.dll
Add-PSSnapin Microsoft.Sharepoint.PowerShell
enable-spfeature $FeatureName -url http:\\url
I have been trying to us the app fabric caching on a win2008 standard server. When I execute the follwowing command I get:
Import-Module DistributedCacheAdministration
Import-Module : The specified module 'DistributedCacheAdministration' was not loaded because no valid module file was found in any module directory.
Where is this directory located and how can I use that module
Also, it appears that I have powershell 1. I cant seem to install powershell 2
Modules and their commands is a feature in Powershell 2 only, so you can be quite certain you're running this version. I guess you're confused because the Powershell.exe is located in a "1.0" directory; that's only to make version 2.0 backwards compatible.
You need to specify the exact location of the module to load: Import-Module [-Force] path-to-module-file`
Even better is have it available via the $PSModulePath environment variable. Try a Get-Module -ListAvailable to see what modules are available. Since the one you're trying to load does not seem to be listed, try setting the $PSModulePath to the folder above the directory holding the module file.
When you're satisfied with having the correct module path, set it via Computer Properties.
I installed AppFabric and the folder shows up at C:\Windows\System32\WindowsPowerShell\v1.0\Modules\DistributedCacheAdministration
Yet Import-Module DistributedCacheAdministration doesn't work and the module isn't listed in Get-Module -ListAvailable