假设我想以非Microsoft语言(在本例中为Java)创建Powershell Commandlet。
显然,这将是一个简单的任务,例如C#-但是我还没有找到任何文档来说明如何(甚至确认是否可能)集成其他语言。
我并不是说要从Powershell(java -jar Thing.jar
或类似名称)中调用Java可执行文件,我希望它的行为与“原生” Powershell Commandlet相同(流水线,获取/设置属性等)。应该从Powershell中隐藏Java语言。
因此:是否存在任何垫片层/库/其他方法可将本机Java代码作为Powershell Commandlet公开?
答案 0 :(得分:0)
我认为您情况下最好的选择是IKVM。该工具将Java字节码转换为CLR字节码,因此,基本上,如果您具有jar或类文件,则可以将其转换为dll,然后将其添加到powershell脚本(或C#代码)中。他们已经转换了Java的标准库,因此您只需要尝试转换jar。没有保证会起作用,尤其是对于某些较新的库,但机会很大。我能够转换几个jdbc驱动程序,并在powershell中使用它们
下面是一个示例(连接到Oracle数据库):
# Download an extract IKVM to any folder
# cd C:\temp\ikvm\bin\
# convert jar to dll with ikvmc: ikvmc -target:library C:\jdbc\ojdbc6.jar
Add-Type -Path "C:\temp\ikvm\bin\ojdbc6.dll"
Add-Type -Path "C:\temp\ikvm\bin\IKVM.OPenJDK.Jdbc.dll"
Add-Type -Path "C:\temp\ikvm\bin\IKVM.OPenJDK.Core.dll"
$url = "jdbc:oracle:thin:@localhost:1521/someServiceName"
$driver = [oracle.jdbc.driver.OracleDriver]::new()
$props = [java.util.Properties]::new()
$props.setProperty("user", "someUser")
$props.setProperty("password", "somePassword")
$conn = $driver.connect($url, $props)
$cmd = $conn.createStatement()
$r = $cmd.executeQuery("select * from all_tables where rownum < 20")
Write-Host "column count: $($r.getMetaData().getColumnCount())"
while($r.next()){
$row = foreach($c in 1..20){ $r.getString($c)}
Write-Host ($row -join "|")
}
另一个选择是使用JVM api。似乎唯一的免费工具是Jni4net。它将jars转换为代理(dll),您可以在.net项目中使用该代理与JVM交互。因此,您需要安装Java才能使其正常工作。我能够构建他们的示例应用程序,但无法为我正在使用的任何jdbc生成代理。您可以给它一个机会,但是我认为它比第一种选择的可靠性低得多。首先下载二进制文件,然后按照说明生成代理: https://github.com/jni4net/jni4net/wiki/Generating-Proxies
如果以上方法均无效,则探索Jython,Groovy等。
在我看来,为“ java -jar myJar ...”创建包装不是一个坏选择。如果您的Java应用程序将结果打印到标准输出中,那么将其与cmdlet集成并使用您需要的所有PS语法糖应该不是问题。 以下是将此jdbc tool包装为cmdlet的示例:
function Invoke-Jdbc { param(
$java="Java" # or path to java exe
, $format="EXCEL"
, $driver = "C:\jdbc\jdbcsql.zip"
, $dbtype, $hostname, $port, $db, $user, $password, $query
)
$data = &$java -jar $driver -f $format -m $dbtype -host $hostname -port $port -d $db -U $user -P $password $query
Write-Output -NoEnumerate ($data | ConvertFrom-Csv -Delimiter "`t" | Out-DataTable)
}
$oracle = @{
dbtype = "oracle"
hostname = "localhost"
port = "1521"
db = "ServiceNameOrSID"
user = "user"
password = "password"
query = "select owner, table_name from all_tables"
}
$dt = Invoke-JDBC @oracle