edit: My issue was never quite resolved, but the answer below provided an interesting result.
The app will eventually be called by a powershell script and in this situation, I don't have the issue explained below. No additional {ENTER} is required in the PS console, so no more issue! I couldn't care less if an extra ENTER is required when my app is launched manually via cmd.exe
Problem: In a VB.NET
form app, I'm unable to get the console back to it's "default" state after the code is finished running. I need to press enter manually.
My app can also be executed from command line (in this case, no form is opened. Code is being executed automatically and output sent to console for user to see what happens)
I call AttachConsole(-1), run some code, and when everything's finished I see my latest message in console, but it's as if the process wasn't quite finished.
I have tried SendKeys.SendWait("{ENTER}"). It works well, but only when the console is the current focus. If I click outside the console while the code is running, the ENTER key is sent to whichever window I made active.
So I tried to make the console the current window:
Dim bProcess As Process = Process.GetProcessesByName("cmd").FirstOrDefault()
SetForegroundWindow(bProcess.MainWindowHandle)
// I also tried AppActivate(bProcess.Id)
SendKeys.SendWait("{ENTER}")
FreeConsole()
Nope, the ENTER key will still be sent somewhere else and not to the console. But it does make the console blink orange, so SetForegroundWindow seems to do something...
Any help will be greatly appreciated :)
EDIT
In response to #TnTinMn's answer:
FreeConsole()
// SendKeys.SendWait("test")
PieceOfCodeFromTnTinMn()
Same behavior as I've had so far: This will send the SendKeys.SendWait("~")command "outside" the console if it loses focus while the code is running.
BUT with the 2nd line above un-commented, "test" is sent outside the console and SendKeys.SendWait("~") is sent to the console, as expected.
I'm still trying to figure out what is happening here...
You can use the VB Interaction.AppActivate Method to activate the parent console prior to calling SendKeys.SendWait. This requires that you obtain the ProcessID of the console window that is the parent process of your application.
One way to do this is using Windows Management Instrumentation (WMI). The following is not pretty, but it appears to work. You would execute this after calling FreeConsole
Using currentProcess As Process = Process.GetCurrentProcess
Dim query As New SelectQuery()
Dim props As New StringCollection
props.Add("ProcessId")
props.Add("ParentProcessId")
With query
.ClassName = "Win32_Process"
.Condition = $"ProcessId={currentProcess.Id}"
.SelectedProperties = props
End With
Dim parentProcessId As Int32
Using searcher As New ManagementObjectSearcher(query)
Using mos As ManagementObjectCollection = searcher.Get
Using en As ManagementObjectCollection.ManagementObjectEnumerator = mos.GetEnumerator
If en.MoveNext() Then
parentProcessId = CInt(en.Current.Item("ParentProcessId"))
End If
End Using 'en
End Using ' mos
End Using 'searcher
If parentProcessId <> 0 Then
AppActivate(parentProcessId)
SendKeys.SendWait("~")
End If
End Using 'currentProcess
Related
I've been trying to access a new window (well tab) when using Capybara, but keep getting
Selenium::WebDriver::Error::NoSuchWindowError: no such window
My process and understanding so far is
#session_1 = Capybara::Session.new(:chrome)
#session_1.visit("www.google.com")
So at this stage i have google open. Now lets say i want to open google in a new tab/window
#session_1.open_new_window
This opens a new window, and to access those windows I can do
#session_1.windows
which returns an array of windows
[#<Window #handle="CDwindow-09B6E81E-7874-4686-86A9-8BFB917E0F4F">,
#<Window #handle="CDwindow-5DA14173-8D63-422A-BF98-39B7C2A5D2DB">]
So as a test I wanted to check that latest windows url matches about:blank
#new_tab = #session_1.windows.last
# #new_tab = #<Window #handle="CDwindow-5DA14173-8D63-422A-BF98-39B7C2A5D2DB">
page.within_window #new_tab do
expect(current_url).to eq('about:blank')
end
It's here I get the error.
What I would like to know is
1) How to select the new tab
2) how to open a new url within the new tab
So I found the answer, turns out it was a lot simpler than i was trying, credit goes to Keiran Betteley and this post
#session_1.open_new_window
#session_1.switch_to_window(#session_1.windows.last)
#session_1.visit("url")
Capybara has a number of methods for dealing with windows, and open_new_window returns the window it opened so there's no need to go looking through the list of all windows
#session1.within_window(#session_1.open_new_window) do
#sessuion1.visit("url")
... more actions performed in the new window
end
I'm having trouble getting through basic authentication on one of our websites on IE8 using Watir.
When I navigate(goto) the url, the basic authentication dialog is displayed showing 'Connect to ' as the title, with user name, password edit fields and OK, Cancel buttons (the usual!).
In Watir, after passing the following code:
b = Watir::Browser.new
b.goto '<our url>'
the dialog is displayed but the goto statement never completes. If I cancel or login manually, then the goto statement returns a number (this is in IRB by the way).
I've done lots of investigation and tried out all sorts of ideas but now seem to be stumped!
When we login to the site manually, we have to pass our credentials like below:
User Name: <domain>\<username>
Password: <password>
I've tried this in the url string i.e.
http://<domain>\<username>:<password>#<url>:<port>
http://lnd\mbartram:mypassword#xxx.xx.xx.xx:xxxx
but this doesn't work in code or if I enter it manually in the address bar.
Perhaps I need to escape the \ part to get this to work but how?
Any help is greatly appreciated.
M.
Ok, using a bit of a hack but it works consistently for me. I'm using a simple Wscript.Shell SendKeys method. See below:
`start #{theURL]`
loginDialog = WIN32OLE.new('Wscript.Shell')
loginDialog.AppActivate('Connect to #{ip}')
sendKeys = "#{userName}{TAB}"
loginDialog.SendKeys(sendKeys)
sleep(1)
sendKeys = "#{password}{TAB}{ENTER}"
loginDialog.SendKeys(sendKeys)
Never mind. The reason this did not work: I forgot to meteor reset so debugger did not get a chance to stop. Duh!
More info: I am using the method in the answer by Mason Chang to the related question, not the kill -s USR1 [proc_id] (where I could see the scripts, but not able to stop in the startup() function.). Also, I am using meteorite.
I am trying to debug the Meteor.startup(function ()) code on Meteor server side (i.e., under /server) with node-inspector, I have read this question, and following the answer to change run.js, but somehow, my own script for the startup function does not show up in the scripts section of Chrome.
How do I see my code here and set break points and stop at those points? BTW, the Meteor_debug() does not output anything to stdout, stderr, or node-inspector browser console. I also tried console.log() with no avail. How to enable logging on Meteor server side?
If it matters, I am on auth branch.
The code here is very simple (/server/bootstrap.js):
Meteor.startup(function () {
if (Logs.find().count() === 0) {
var data = [/*...some data...*/];
var timestamp = (new Date()).getTime();
Meteor._debug("timestamp: "+timestamp+", data.len: " + data.length);
debugger;
for (var i = 0; i < data.length; i++) {
data[i].timestamp = timestamp++;
var entry_id = Logs.insert(data[i]);
Meteor._debug("entry_id: "+ entry_id);
}
}
});
Now that I know how to do this, I will answer my own question so that we can keep this information (in details) here: (This is based on Mason Chang's answer to this question.)
Stop meteor execution.
Edit /usr/lib/meteor/app/meteor/run.js (or the corresponding run.js installed by meteorite in HOME//.meteorite/meteors/meteor/meteor/[LONG_HEX_CODE]/app/meteor):
change the line
[path.join(bundle_path, 'main.js'), '--keepalive']
to
['--debug-brk', path.join(bundle_path, 'main.js'), '--keepalive']
//--debug-brk makes the new thread break at the first line;
Add debugger statements as breakpoints in your server code;
Run node-inspector & in a server terminal. (google "node-inspector" to install it.)
Run meteor; (this will not have the debugger attached as there's no server thread yet, if you have no client window open.)
Refresh client browser window; (to initiate a server thread that will break at the first line, and be attached to node-inspector.)
Open a browser window at [SERVER:8080], your server code stops at first line (main.js in your [PROJECT_DIR]/.meteor/local/build);
Hit the RUN button on the debugger browser window; depending on where your debugger statements are, you may have to do some triggering actions in client browser window to run to the debugger breakpoints. (Note that if you wait too long to hit the RUN button, your client window may time out, and you have to refresh again.)
Now you can do the usual debugging stuff in server debugger window: step through, watch variables, execute in console, look at the stack, etc.
Edit: For logging on server side, you can use either Meteor._debug() and console.log(), they will show up in the terminal where you run meteor. On client side, these logging statements will output to the console of your browser's dev. tools.
On MacOSX, you can use with Chrome :
NODE_OPTIONS="--debug-brk" meteor
and in another terminal
node-inspector --debug-port=5858 --web-port=12345
Then connect Chrome to 127.0.0.1:12345/debug?port=5858
Otherwise with Webstorm, just create a Node.js Remote Debug configuration and run it :
Name : Meteor
Host : 127.0.0.1
Port 5858
Note that once the server has started, you need to press run in order for Meteor to load, and then pause in order to debug from the server console.
I've been tasked with converting a legacy application to mvc. The app used pgp.exe to pgp sign user input and send it as an email. The application works locally and on a test server but won't run on a live server. I've had to jump though hoops such as running a specified user in the application pool so that we can set the keys in the users profile BUT it worked.
For some reason on the live server which is windows 2003 IIS 6 and identical to the testing server it fails. The problem is pgp.exe just wont seem to sign and create files the message I get from the console out put is. "Signature Error"?? When I put the command into a shell window logged in as the app pool user it runs no problem (after a fight with some permissions) but when running through the mvc application/IIS server it fails. The code used to call the process is below.
var startInfo = new ProcessStartInfo();
startInfo.FileName = _pgpexeLocation;
//startInfo.FileName = "pgp.exe";
startInfo.Arguments = string.Format("-sta \"{0}\" -u keyuser-z keypass +COMPATIBLE +FORCE", _tempFilePath);
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.LoadUserProfile = true;
using (Process exeProcess = Process.Start(startInfo))
{
// TODO: set limit to wait for and deal with exit
exeProcess.WaitForExit();
//var stringItem = exeProcess.StandardOutput.ReadToEnd();
//Logger.Info(stringItem);
}
I'm clutching at straws here hoping somebody has done something similar before and can help. I'm guessing it's key location or file location not being picked up somewhere but not sure what else to try?
Turns out that even though the app pool was using a specific user and I'd set the keys up in that users appdata folder when I checked the underlying process call it was actually trying to pick the keys up from the Default User profile. Not sure if this was an IIS config or something similar but moving the keys and pgp folder to this appdata instead worked?
Some Background on architecture of the app is needed:
Windows 2003/Apache-v2.2/IE7/Watir-v1.6.2/Ruby-v1.8.5
Apache running under 'localsystem' account.
Request to run a Watir script comes in.
Apache CGI kicks off IE7 under a particular user, e.g. 'tester', and attaches the IE7 window to the "default" desktop environment. This allows us to VNC into the machine and see all IE7 windows from all the accounts running.
IE7 has ruby embedded into the process through plugin and executes the ruby script in a thread.
For clicking on links/buttons in IE, Watir supplies a synchronous 'click' method and async 'click_no_wait' method. 'click_no_wait' spawns a completely new ruby process to connect back to the IE7 window to click the link/button.
This is what is failing for me. Since click_no_wait is spawning a new process. It cannot seem to see the IE7 window to connect to it and click on the link/button.
I have to use 'click_no_wait' due to a dialog box that IE pops up on a certain page, so that another ruby thread can close it.
I've tried a few things:
- using fire_event('OnClick') instead of click_no_wait hangs script like 'click' would.
- Modifying 'click' by commenting out '#container.wait', but the 'click!' itself is the API that hangs waiting for the dialog box to close.
- Make 'click_no_wait' spawn a new thread instead of a process', but other threads appear to be suspended while the 'click!' call executes in that thread. Which is strange.
- Executing the 'click_no_wait' process using the exact same code that is used to spawn the IE7 process, but it still can't find any IE7 windows.
By 'default' desktop described above, the code that spawns IE basically does a series of C++ calls to attach the IE7 window to the 'winsta0' desktop:
- LogonUser() // log in as tester account
- OpenWindowStation("winsta0") // to get default desktop
- SetProcessWindowStation()
- // add the user to interactive window station using (GetUserObjectSecurity, GetSecurityDescriptorDacl, GetAclInformation, AddAce, SetSecurityDescriptorDacl, SetUserObjectSecurity)
- // add user to "default" desktop using APIs listed above.
- CreateEnvironmentBlock
- ImpersonateLoggedOnUser
- CreateProcessAsUser('iexplore.exe')
- // cleanup
Running the following Watir script under the particular user IE7 is running under yields:
$IE = Watir::IE.attach(:title, /Google/)
$IE.button(:name, 'btnG').click!
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246:in `method_missing': Windows (WIN32OLERuntimeError)
OLE error code:80040154 in
HRESULT error code:0x80020009
Exception occurred. from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246:in "each"
Which contains:
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246
shell = WIN32OLE.new("Shell.Application")
windows = shell.Windows ## Fails here
Let me know if I can supply more details or disambiguation! :)
Thanks,
Shane.
Ok, I have solved my own issue.
It turns out that the method that Watir uses to enumerate IE windows (i.e. Shell.Application) does not work across user spaces. So I had to write an intermediate application to retrieve the IWebBrowser2 COM pointer for the IE window, and modify the 'eval_in_spawned_process' Watir function to use this handle for 'pc = Watir::IE.bind(iWebBrowserPtr)'.
It's possible that I didn't need the external app to retrieve the IWebBrowser2 object, but I didn't know how to do it in Ruby, and I already had an IE BHO app that I could leverage for the purposes.
This now works fine. :)
Watir/page-container.rb:56
# This evaluates a cmd (e.g. "button(:id, 1).click!") in a new ruby process
# This is to primarily avoid a script hanging while a modal dialog is displayed in IE.
# It gets an IE handle from our IE BHO based off of window handle. It needs to do this
# to get around the problem of finding the IE window itself using Shell.Application
# which does not work across User-contexts.
# Note: This change probably invalidates the Watir unit-test for this API.
def eval_in_spawned_process(command)
command.strip!
load_path_code = _code_that_copies_readonly_array($LOAD_PATH, '$LOAD_PATH')
ruby_code = "require 'watir/ie'; "
ruby_code << 'controller = WIN32OLE.new("HttpPlugin.Controller"); '
ruby_code << "window = controller.BrowserFromHWND(#{hwnd}); "
ruby_code << "pc = Watir::IE.bind(window); "
ruby_code << "pc.#{command}; "
exec_string = "start rubyw -e #{(load_path_code + '; ' + ruby_code).inspect}"
result = system(exec_string)
end