ASP.NET: Execute an external executable doesn't work - asp.net

I need help with the code below.
I try to convert a AutoCAD file from the format dwg to the format dwf.
Then, the dwf file is downloaded and opened on the client computer using a java applet.
The command used to convert the dwg file on the command-line is:
C:\inetpub\wwwroot\COR-Basic\cadviewer\converter\ax2008.exe -i="C:\inetpub\wwwroot\test\container\DU38_EG00_070116.dwg" -o="C:\inetpub\wwwroot\COR-Basic\cadviewer\files\DU38_EG00_070116.dwf" -f=dwf -model -text
this works when I enter the command text in cmd.exe.
But when I call it from my asp.net application, it only starts the process, but the process never ends...
I've tried adding an additional user, have given this user full permission, and full permissions on wwwroot, but it still doesn't work.
Anybody knows what I'm doing wrong, or how I could do it in another way?
If System.IO.File.Exists(strDWGlocation) Then
Dim psiProcessSettings As Diagnostics.ProcessStartInfo = New Diagnostics.ProcessStartInfo
psiProcessSettings.FileName = strApplicationPath
psiProcessSettings.Arguments = " -i=""" & strDWGlocation & """ -o=""" & strOutputLocation & """ -f=dwf -model -text"
'ST-LAPTOP\converter
psiProcessSettings.UserName = "converter"
psiProcessSettings.Password = secureString
'StefanSteiger.Debug.MsgBox("Input location:" + strDWGlocation)
'StefanSteiger.Debug.MsgBox("Output location:" + strOutputLocation)
Response.Write("<h1>Argument1: " + psiProcessSettings.Arguments + "</h1>")
Response.Write("<h1>Pfad1: " + psiProcessSettings.FileName + "</h1>")
'psiProcessSettings.RedirectStandardInput = True
psiProcessSettings.RedirectStandardError = True
psiProcessSettings.RedirectStandardOutput = True 'Redirect output so we can read it.
psiProcessSettings.UseShellExecute = False 'To redirect, we must not use shell execute.
'psiProcessSettings.CreateNoWindow = True ' don't create a window
Dim pConverterProcess As Diagnostics.Process = New Diagnostics.Process
pConverterProcess = Diagnostics.Process.Start(psiProcessSettings) 'Create the process.
pConverterProcess.Start() 'Execute the process.
'Response.Write("<h1>" + Replace(pConverterProcess.StandardOutput.ReadToEnd(), vbCrLf, "<BR />") + "</h1>") 'Send whatever was returned through the output to the client.
'pConverterProcess.CancelOutputRead()
'pConverterProcess.CancelErrorRead()
'pConverterProcess.StandardInput.Close()
'Wait for the process to end.
'pConverterProcess.WaitForExit()
pConverterProcess.Close()
'Dim iExitCode As Integer = pConverterProcess.ExitCode()
pConverterProcess.Dispose()
Else
MyNamespace.Debug.MsgBox("No such file.")
End If

This is my code that does a similar thing, and it works!
process.StartInfo.FileName = toolFilePath;
process.StartInfo.Arguments = parameters;
process.StartInfo.UseShellExecute = false; // needs to be false in order to redirect output
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true; // redirect all 3, as it should be all 3 or none
process.StartInfo.WorkingDirectory = Path.GetDirectoryName(toolFilePath);
process.StartInfo.Domain = domain;
process.StartInfo.UserName = userName;
process.StartInfo.Password = decryptedPassword;
process.Start();
output = process.StandardOutput.ReadToEnd(); // read the output here...
process.WaitForExit(); // ...then wait for exit, as after exit, it can't read the output
returnCode = process.ExitCode;
process.Close(); // once we have read the exit code, can close the process

Why have you commented out the WaitForExit()?
You could try setting EnableRaisingEvents to true as well.
In my experience, the Process class is quite difficult to work with when reading the standard output, try removing any code that attempts to redirect and read output

Related

Check if Image Exists on Remote Site ASP.NET VB

I'm trying to get my website to detect if an image exists on the server, display if it does, if it doesn't display another image (which is just called blank.png).
I have tried to use Server.MapPath with relative pathings but havent been able to get it to work. When using Server.MapPath and checking in the broswer after the page has loaded i uses the full path of the file (eg G:\domain\path\blank.png).
If i use The normal path (Dim sImagePath As String = "\Images\DriversNew\"'). The image will display, but the check for whether the image exists or not always returns false. I'm assuming its to do with the physical location of the file.
'Dim sImagePath As String = Server.MapPath("Images/DriversNew/")
Dim sImagePath As String = "\Images\DriversNew\"
Dim sHeadshot As String = sImagePath & dsDriver.Tables("Driver").Rows(0).Item("Name") & ".png"
If File.Exists(sHeadshot) Then
imgDriver.ImageUrl = sHeadshot
Else
imgDriver.ImageUrl = sImagePath & "Blank.png"
End If
Any advice? I know its something simple, but with the reading ive been doing it hasnt been able to get it working on the site.
Thanks, much appreciated!
Assuming that your database column Name contains only the short filename (i.e. no directory path information or folder names) then you can do this:
String nameFromDatabase = (String)dsDriver.Tables("Driver").Rows[0]["Name"] + ".png";
String appRootRelativeHttpResourcePath = "~/Images/DriversNew/" + nameFromDatabase;
String localFileSystemPath = Server.MapPath( appRootRelativeHttpResourcePath );
if( File.Exists( localFileSystemPath ) ) {
imgDriver.ImageUrl = appRootRelativeHttpResourcePath; // you can specify app-root-relative URLs ("~/...") here
}
else {
imgDriver.ImageUrl = "~/Images/DriversNew/Blank.png";
}

Encrypted cookies in Chrome

I am currently working on a C# forms application that needs to access a specific cookie on my computer, which I can do perfectly fine. Here's the issue:
Google stores cookies in SQLite, and I've downloaded Sqlite database browser to help me look at these values. What surprises me is that about half of the cookie values shows as empty (including the one I need), even though they are obviously not.
The db file is located at:
C:\Users\%username%\AppData\Local\Google\Chrome\User Data\Default\Cookies
On Chrome I have an addon called "Edit This Cookie" which allows me to directly modify cookies on the website I'm on. This addon can read these cookies, and the web browser can parse values through HTTP when needed for different requests, so they are definitely there - still, the SQLite browser, and my custom code both come to the conclusion that the particular value field is empty.
Why is that?
What is it that somehow prevents the field from being read by certain applications?
I've run into this same problem, and the code below provides a working example for anyone who is interested. All credit to Scherling, as the DPAPI was spot on.
public class ChromeCookieReader
{
public IEnumerable<Tuple<string,string>> ReadCookies(string hostName)
{
if (hostName == null) throw new ArgumentNullException("hostName");
var dbPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + #"\Google\Chrome\User Data\Default\Cookies";
if (!System.IO.File.Exists(dbPath)) throw new System.IO.FileNotFoundException("Cant find cookie store",dbPath); // race condition, but i'll risk it
var connectionString = "Data Source=" + dbPath + ";pooling=false";
using (var conn = new System.Data.SQLite.SQLiteConnection(connectionString))
using (var cmd = conn.CreateCommand())
{
var prm = cmd.CreateParameter();
prm.ParameterName = "hostName";
prm.Value = hostName;
cmd.Parameters.Add(prm);
cmd.CommandText = "SELECT name,encrypted_value FROM cookies WHERE host_key = #hostName";
conn.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var encryptedData = (byte[]) reader[1];
var decodedData = System.Security.Cryptography.ProtectedData.Unprotect(encryptedData, null, System.Security.Cryptography.DataProtectionScope.CurrentUser);
var plainText = Encoding.ASCII.GetString(decodedData); // Looks like ASCII
yield return Tuple.Create(reader.GetString(0), plainText);
}
}
conn.Close();
}
}
}
Alright, so in case anyone is interested, I found a solution to this problem after alot of trial, error and googling.
Google Chrome cookies DB has 2 columns for storing values: "value" and "encrypted_value", the latter being used when the cookie stored was requested to be encrypted - often the case with certain confidential information and long-time session keys.
After figuring this out, I then needed to find a way to access this key, stored as a Blob value. I found several guides on how to do this, but the one that ended up paying of was: http://www.codeproject.com/Questions/56109/Reading-BLOB-in-Sqlite-using-C-NET-CF-PPC
Simply reading the value is not enough, as it is encrypted. - Google Chrome uses triple DES encryption with the current users password as seed on windows machines. In order to decrypt this in C#, one should use Windows Data Protection API (DPAPI), there are a few guides out there on how to make use of it.
Like Jasper's answer, in a PowerShell script (of course, customize the SQL query to your needs, and the path to your cookies location):
$cookieLocation = 'C:\Users\John\AppData\Local\Google\Chrome\User Data\Default\cookies'
$tempFileName = [System.IO.Path]::GetTempFileName()
"select writefile('$tempFileName', encrypted_value) from cookies where host_key = 'localhost' and path = '/api' and name = 'sessionId';" | sqlite3.exe "$cookieLocation"
$cookieAsEncryptedBytes = Get-Content -Encoding Byte "$tempFileName"
Remove-Item "$tempFileName"
Add-Type -AssemblyName System.Security
$cookieAsBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($cookieAsEncryptedBytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
$cookie = [System.Text.Encoding]::ASCII.GetString($cookieAsBytes)
$cookie
So I wanted to do this without writing to a tempfile every time but also without implementing a separate class as per jasper's solution. Like jasper, I found it easier and quicker to access the System.Data.SQLite.dll available here. It's not as elegant as a separate class, but it's what worked best for me:
Add-Type -AssemblyName System.Security
Add-Type -Path 'C:\Program Files\System.Data.SQLite\2015\bin\x64\System.Data.SQLite.dll'
Function Get-Last-Cookie {
Param(
[Parameter(Mandatory=$True)] $valueName,
[Parameter(Mandatory=$True)] $hostKey,
[Parameter(Mandatory=$True)] $dbDataSource
)
$conn = New-Object -TypeName System.Data.SQLite.SQLiteConnection
$conn.ConnectionString = "Data Source=$dbDataSource"
$conn.Open()
$command = $conn.CreateCommand()
$query = "SELECT encrypted_value FROM cookies WHERE name='$valueName' `
AND host_key='$hostKey' ORDER BY creation_utc DESC LIMIT 1"
$command.CommandText = $query
$adapter = New-Object -TypeName System.Data.SQLite.SQLiteDataAdapter $command
$dataset = New-Object System.Data.DataSet
[void]$adapter.Fill($dataset)
$command.Dispose();
$conn.Close();
$cookieAsEncryptedBytes = $dataset.Tables[0].Rows[0].ItemArray[0]
$cookieAsBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($cookieAsEncryptedBytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
return [System.Text.Encoding]::ASCII.GetString($cookieAsBytes)
}
$localAppDataPath = [Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData)
$cookieDbPath = 'Google\Chrome\User Data\Default\Cookies'
$dbDataSource = Join-Path -Path $localAppDataPath -ChildPath $cookieDbPath
$plainCookie = Get-Last-Cookie 'acct' '.stackoverflow.com' $dbDataSource
Write-Host $plainCookie
I also found the Add-SqliteAssembly function by halr9000 to be very helpful when it came time to schedule my script in the windows task scheduler and realized that the task scheduler runs the x86 version of PowerShell and thus SQLite rather than the x64 I was using in the console.
The thing is that Google Chrome encrypts the data you need to read, so you have to decrypt it.
First, get a copy of the cookies file. Then read it using SQLite3. After that, get the encrypted bytes. And last, use the code below to decrypt it.
You'll need these Nugets:
using System.IO;
using System.Net;
using System.Data.SQLite;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto;
using Newtonsoft.Json.Linq;
The code so far:
File.Copy(Environment.GetEnvironmentVariable("APPDATA") + #"/../Local/Google/Chrome/User Data/Default/Cookies", #"./Cookies",true);
SQLiteConnection Cnn = new SQLiteConnection("Data Source=" + #"./Cookies" + ";pooling=false");
Cnn.Open();
SQLiteCommand cmd = new SQLiteCommand("SELECT host_key, name, value, encrypted_value FROM cookies WHERE name='mvrusername' OR name='mvrcookie' OR name='mikuki4'", Cnn);
SQLiteDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
byte[] encryptedData = (byte[])rdr["encrypted_value"];
string encKey = File.ReadAllText(Environment.GetEnvironmentVariable("APPDATA") + #"/../Local/Google/Chrome/User Data/Local State");
encKey = JObject.Parse(encKey)["os_crypt"]["encrypted_key"].ToString();
var decodedKey = System.Security.Cryptography.ProtectedData.Unprotect(Convert.FromBase64String(encKey).Skip(5).ToArray(), null, System.Security.Cryptography.DataProtectionScope.LocalMachine);
const int MAC_BIT_SIZE = 128;
const int NONCE_BIT_SIZE = 96;
using (var cipherStream = new MemoryStream(encryptedData))
using (var cipherReader = new BinaryReader(cipherStream))
{
var nonSecretPayload = cipherReader.ReadBytes(3);
var nonce = cipherReader.ReadBytes(NONCE_BIT_SIZE / 8);
var cipher = new GcmBlockCipher(new AesEngine());
var parameters = new AeadParameters(new KeyParameter(decodedKey), MAC_BIT_SIZE, nonce);
cipher.Init(false, parameters);
var cipherText = cipherReader.ReadBytes(encryptedData.Length);
var plainText = new byte[cipher.GetOutputSize(cipherText.Length)];
try
{
var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0);
cipher.DoFinal(plainText, len);
}
catch (InvalidCipherTextException)
{
}
string _cookie= Encoding.Default.GetString(plainText);
}
}
// Big thanks to https://stackoverflow.com/a/60611673/6481581 for answering how Chrome 80 and up changed the way cookies are encrypted.
# this powershell scripts exports your cookies to a format curl and wget understand
# Obs ! Each profile has its own cookes file , replace me (ysg ;o) with your win usr name
# aka wget -x --load-cookies cookies.txt http://stackoverflow.com/questions/22532870/encrypted-cookies-in-chrome
$cookieLocation = 'C:\Users\ysg\AppData\Local\Google\Chrome\User Data\Profile 1\Cookies'
$curl_cookies_file="C:\var\ygeo.reports.app.futurice.com.cookies.doc-pub-host.txt"
$tempFileName1 = [System.IO.Path]::GetTempFileName()
$tempFileName2 = [System.IO.Path]::GetTempFileName()
# adjust your filter in the where clause ...
"select writefile('$tempFileName1', encrypted_value) from cookies where host_key = '.futurice.com' ;" | sqlite3.exe "$cookieLocation"
$cookieAsEncryptedBytes = Get-Content -Encoding Byte "$tempFileName1"
Remove-Item "$tempFileName1"
Add-Type -AssemblyName System.Security
$cookieAsBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($cookieAsEncryptedBytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
$cookie = [System.Text.Encoding]::ASCII.GetString($cookieAsBytes)
$unquoted_cookie=$cookie -replace '"', ""
# adjust your filter in the where clause ...
"
select
host_key
, CASE WHEN httponly=0 THEN 'FALSE' ELSE 'TRUE' END
, path
, CASE WHEN secure=0 THEN 'FALSE' ELSE 'TRUE' END
, expires_utc
, name
, '$unquoted_cookie'
from cookies where host_key = '.futurice.com' ;" | sqlite3.exe -separator " " "$cookieLocation" > $curl_cookies_file
Get-ChildItem *.txt | ForEach-Object { (Get-Content $_) | Out-File -Encoding ASCII $_ }
# check the meta data table
#"PRAGMA table_info([cookies]);" | sqlite3.exe "$cookieLocation"
# src: https://github.com/daftano/cookies.txt/blob/master/src/popup.js
#content += escapeForPre(cookie.domain);
#content += "\t";
#content += escapeForPre((!cookie.hostOnly).toString().toUpperCase());
#content += "\t";
#content += escapeForPre(cookie.path);
#content += "\t";
#content += escapeForPre(cookie.secure.toString().toUpperCase());
#content += "\t";
#content += escapeForPre(cookie.expirationDate ? Math.round(cookie.expirationDate) : "0");
#content += "\t";
#content += escapeForPre(cookie.name);
#content += "\t";
#content += escapeForPre(cookie.value);
#content += "\n";
#
#0|creation_utc|INTEGER|1||1
#1|host_key|TEXT|1||0
#2|name|TEXT|1||0
#3|value|TEXT|1||0
#4|path|TEXT|1||0
#5|expires_utc|INTEGER|1||0
#6|secure|INTEGER|1||0
#7|httponly|INTEGER|1||0
#8|last_access_utc|INTEGER|1||0
#9|has_expires|INTEGER|1|1|0
#10|persistent|INTEGER|1|1|0
#11|priority|INTEGER|1|1|0
#12|encrypted_value|BLOB|0|''|0
#13|firstpartyonly|INTEGER|1|0|0
Just set "value" to the cookie you want, "encrypted_value" to NULL and "priority" to 0

Having an issue running an external program with arguments

I do have a final issue to my project and I just can't see clear enought to find out what the hell is wrong here.
When I run my code with this, everything is just perfect:
Dim p As Process = New Process()
With p.StartInfo
.WorkingDirectory = Environment.GetEnvironmentVariable("ProgramFiles") & "\rest_of_my_path\"
.FileName = "ping"
.Arguments = "192.168.0.24"
.CreateNoWindow = True
.UseShellExecute = False
.RedirectStandardOutput = True
.RedirectStandardError = True
End With
p.Start()
However, when I run this, it throughs an error during runtime and crashes on p.start()
Dim p As Process = New Process()
With p.StartInfo
.WorkingDirectory = Environment.GetEnvironmentVariable("ProgramFiles") & "\rest_of_my_path\"
.FileName = "myextprogram.exe"
.Arguments = "-n Unnamed -f file.abc"
.CreateNoWindow = True
.UseShellExecute = False
.RedirectStandardOutput = True
.RedirectStandardError = True
End With
p.Start()
I tried adding spaces, quotation marks, just name it but ALWAYS getting an Exception has been thrown by the target of an invocation.
I believe it's complaining about the path.
I'm almost sure it's simple but just cannot put my finger on it.
Any help is appreciated.
ok, found a fix...if anybody is interested...
Rather than having
.FileName = "myextprogram.exe"
.Arguments = "-n Unnamed -f file.abc"
I now have
.FileName = "cmd"
.Arguments = "myextprogram.exe -n Unnamed -f file.abc"
Everything is working as expected now.

Show Log of a file in jgit when committng it as a BLOB

Implemented the above logic to create a new commit (with no parents) that contains only my file. Commits are fast in the repository as compared to CommitCommand commit = git.commit();
But I am not able to get the Logs of a particular file , the number of times it has been updated/revised , and every time i go for Constants.HEAD , I am getting null.
Any help will be of great advantage.
Git git = jGitUtil.openRepo();
Repository repository = git.getRepository();
ObjectInserter repoInserter = repository.newObjectInserter();
ObjectId commitId = null;
try
{
byte[] fileBytes= FileUtils.readFileToByteArray(sourceFile);
// Add a blob to the repository
ObjectId blobId = repoInserter.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, fileBytes);
// Create a tree that contains the blob as file "hello.txt"
TreeFormatter treeFormatter = new TreeFormatter();
treeFormatter.append(actualFileName, FileMode.REGULAR_FILE, blobId);
ObjectId treeId = treeFormatter.insertTo(repoInserter);
System.out.println("File comment : " + relativePath + PortalConstants.FILESEPARATOR + actualFileName + PortalConstants.EP_DELIMETER + userComments);
// Create a commit that contains this tree
CommitBuilder commit = new CommitBuilder();
PersonIdent ident = new PersonIdent(user.getFirstName(), user.getUserId());
commit.setCommitter(ident);
commit.setAuthor(ident);
commit.setMessage(relativePath + PortalConstants.FILESEPARATOR + actualFileName + PortalConstants.EP_DELIMETER + userComments);
commit.setTreeId(treeId);
commitId = repoInserter.insert(commit);
System.out.println(" commitId : " + commitId.getName());
repoInserter.flush();
System.out.println("Flush Done");
}catch(IOException ioe){
log.logError(StackTraceUtil.getStackTrace(ioe));
System.out.println(StackTraceUtil.getStackTrace(ioe));
}
finally
{
repoInserter.release();
}
return commitId.getName();
}
I would probably use Add File and Commit File porcelain commands instead of trying to implement it myself. Then retrieving the log should be possible via something like this:
Iterable<RevCommit> logs = new Git(repository).log()
.all()
.call();
for(RevCommit rev : logs) {
System.out.println("Commit: " + rev + " " + rev.getName() + " " + rev.getId().getName());
}
Where you can retrieve the additional information based on the commit-id.
I have now also added this as new snippet Show Log
Note that if you are creating a commit with no parents, you are saying that there is no history. Therefore you won't be able to see any other changes from that history because it doesn't exist.
You probably should use a commit with the parent of the current position of the branch so that you'll be able to get more information.

Powerbuilder 9- how to use adobe writer instead of Ghostscript for SaveAs()

We have Adobe PDF writer and would like to be able to use this instead of ghostscript. Is the SaveAs() function locked into ghostscript and, if so, how can I use adobe pdf writer to get around this?
I think this could be the solution:
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.dc00844_1150/html/pbug/pbug526.htm
The key change is that you need to create your own printer not using the GhostScript files than the files shipped with Adobe.
I think you should create your Adobe PDF Printer in this way:
http://www.ehow.com/how_5782035_add-adobe-pdf-printer.html
So you should add a local printer with using this file:
C:\Program Files\Adobe\Acrobat 9.0\Acrobat\Xtras\AdobePDF". Click the
"AdobePDF.inf"
After this the code should something similar to this:
int li_ret
dw_1.Object.DataWindow.Export.PDF.Method = Distill!
dw_1.Object.DataWindow.Printer = "YourAdobePDFPrinterName"
dw_1.Object.DataWindow.Export.PDF.Distill.CustomPostScript="Yes"
li_ret = dw_1.SaveAs("custom.PDF", PDF!, true)
Of course there could be many other problems with printing. Feel free to ask!
Br.: Gábor
The SaveAs() function is tied to using Ghostscript, to print using Adobe Acrobat, you treat it as a regular printer. Hopefully PB 9 has these functions as this is taken from PB 11.5.
RegistrySet("HKEY_CURRENT_USER\Software\Adobe\Acrobat Distiller\9.0\AdobePDFOutputFolder", "", ReguLong!, 2)
RegistrySet("HKEY_CURRENT_USER\Software\Adobe\Acrobat Distiller\9.0\AdobePDFOutputFolder", "2", RegString!, "C:\_APPS")
//Gets the default printer
ls_default = PrintGetPrinter()
//Parses string
ll_pos = Pos(ls_default, "~t")
is_default_printer = Left(ls_default, ll_pos - 1)
//Gets the Printers on the computer
ls_printers = PrintGetPrinters( )
//Finds the Distiller printer
ll_pos = PosA(ls_printers, "Acrobat Distiller")
//Checks for newer version of Distiller
if (ll_pos = 0) then
ll_pos = PosA(ls_printers, "Adobe PDF")
end if
//Gets the location of the Distiller printer
ls_printer = MidA(ls_printers, ll_pos, PosA(ls_printers, ":", ll_pos) - ll_pos + 1)
//Sets our next print ll_job to print to Distiller
PrintSetPrinter(ls_printer)
//Allocates memory for our DS
DS = create DataStore
//Opens Print Job
ll_job = PrintOpen("MyPDF", false)
//Checks for error
if (ll_job > 0) then
//First Datastore to add to the PDF
DS.DataObject = "d_wlcp_view"
DS.SetTransObject(SQLCA)
DS.Retrieve(idt_review_date, ii_site_id)
PrintDataWindow(ll_job, DS)
//You can add more pages to the PDF by printing more DW's or DS's
DS.DataObject = "d_training_view"
DS.SetTransObject(SQLCA)
DS.Retrieve(idt_review_date, ii_site_id)
PrintDataWindow(ll_job, DS)
//Closes the print job
PrintClose(ll_job)
//Sets the default printer back
PrintSetPrinter(ls_default)
//Sometimes the PB function doesn't set the printer back, so you can use
//this VB script to make sure it is set back to the default
//Run('cscript C:\_APPS\HWLCPRR\prnmngr.vbs -t -p "' + is_default_printer + '"')
//Deallocates memory for DS
if (isValid(DS)) then destroy DS
Here is the VB Script.

Resources