Detect a remote desktop connection from a service at logon (W7/32) - c#

I know (and it works) that in C#, this property tells me if the current session is a RDP one:
System.Windows.Forms.SystemInformation.TerminalServerSession
Now, I have a service that receives logon/logoff and lock/unlock events, and I need a way to tell this service if the session being started is rdp or local.
Problem: the service runs as SYSTEM user, and the property above always returns false (I think because SYSTEM is always considered a local connected user)
I've tried to search in the register for the Volatile Environment subkey to check if there is the subkey that identify the RDP Session Name: this works in lock/unlock handler, but in the logon handler the subkey doesn't exists yet (subkey is created after login completes).
Any idea about how to work around this problem?
While a wait for the key creation for a limited amount of time works, I would like a less "kludgy" way to do it.

You can detect whether a session is a local or remote session by calling WTSQuerySessionInformation with the WTSInfoClass parameter set to WTSClientProtocolType. If you'd prefer to avoid the P/Invokes, you can use the Cassia library: new TerminalServicesManager().GetLocalServer().GetSession(sessionId).ClientProtocolType.
Caveats: This won't help you when processing session logoff messages because you will not (reliably) be able to fetch information about the session, since it's in the process of being destroyed (but that seems relatively easy to work around). Also, the ClientProtocolType Cassia property mentioned above has not yet been released, but you can grab a trunk build from the build server by logging in as a guest and using the artifacts link.

Related

Cannot login offline

I can login with username and password when internet is connected. If I disconnect internet when logged in I can still listen to offline lists. If I reconnect internet I get full functionality again without any actions on my part.
But when internet is unavailable when I start my application I cannot login to listen to offline tracks.
I have tried to login with blob instead of password without success (with or without internet). I have also played around with "rememberme" but that does not seem to survive a restart of my application.
I have tried empty strings ("") as well as IntPtr.Zero for password and blob when using the other.
No success. What am I doing wrong?
I think that #Kendall Frey hit the nail on the head, offline support is implemented in libspotify, but you probably at least need to be online to get it started. This isn't the case in Spotify's mobile and desktop clients, however they are not built on libspotify. So sorry, I don't believe that there is any way around this limitation.
Offline login should actually work in libspotify using the credentials blob under the following conditions:
The user has successfully logged in online at least once before.
You are allowing libspotify to create and maintain an on-disk cache.
libspotify is able to correctly write credentials to that cache and verify them next time.
You are correctly allowing libspotify to clean up as your application exits.
The cache is the important part here. You must pass libspotify a location on-disk that's readable and writeable.
Also very important is logging out correctly. You must either log out the user and wait for that process to complete as your application exits or call flush_caches() and wait for that to complete. Otherwise, libspotify won't be able to correctly write to the cache to enable offline login next time. If you're just exiting your process without proper libspotify cleanup, offline login won't work.
You were absolutely correct iKenndac!
In fact the problem was behind the keyboard, as I got confused by the connection states and the sp_error of the login callback.
I did in fact log in successfully the same way as I did when connected. That is with username and password and "remember me".
Confusion came from the comments in api.h
SP_CONNECTION_STATE_LOGGED_OUT = 0, ///< User not yet logged in
SP_CONNECTION_STATE_LOGGED_IN = 1, ///< Logged in against a Spotify access point
SP_CONNECTION_STATE_DISCONNECTED = 2, ///< Was logged in, but has now been disconnected
SP_CONNECTION_STATE_UNDEFINED = 3, ///< The connection state is undefined
SP_CONNECTION_STATE_OFFLINE = 4 ///< Logged in in offline mode
When I start my app without internet connection I first get login callback saying SP_ERROR_OK and then I get SP_CONNECTION_STATE_DISCONNECTED (Was logged in, but has now been disconnected)
I expected SP_CONNECTION_STATE_OFFLINE (Logged in in offline mode) when not connected to internet.
But "now working"

How to save clicking counter in c#

I build web-site and want to count clicks on some button. I create and try this class of counter:
public static class Counter
{
public static int counter = 0;
}
Every time I click on the button the counter is increament (counter++) ans I see it in my site, But, if I close the chrome and enter again to my site the counter starts from zero.
How can I save the counter? "Static" dont need to do that?
My bet is that it happens because the application space is flushed - it shouldn't reset just because you closed your browser window, thus abandoning the current session (if the session cookie isn't persistent, that is.)
Visual Studio may republish your files (if using a remote IIS) or just plainly restart a local IIS Express instance, depending on how you set your development environment; I do believe setting a specific content as Static would cause it to be available to all current sessions.
That said, you may want to keep it under the current session (using the Session object).
Optionally, if you want to persist information in between server restarts, you may try reading and writing to a local storage, such as a plaintext or XML file. You can find a very nice article about this on the following link:
http://www.codeproject.com/Articles/544839/Implement-ASP-NET-custom-XML-file-configuration
A more sophisticated version would use a local (or remote) database, for example.
Hope it works for you.
static fields are unique per-process. Depending on your application pool configuration, you could have 2, 20 or 100 copies of that.
They're also not thread safe. There are very, very few instances (pun) where a static member is appropriate.
Just off the top of my head, a particular "instance" of a static will disappear when:
The application pool is recycled. On IIS, this defaults to 20 minutes of inactivity.
The application process exits (you may have multiple processes running within your app pool). This happens as part of (1), but will also happen if, say, you're using the Visual Studio debug web server (Cassini), have your project configured to launch the site for debugging, and close the browser that was launched initially. (This happens because VS considers closing the browser that it launched equivalent to saying "I'm done playing. Back to coding now," or hitting the stop button.)
Another thread overwrites the value you've stored (google "race condition.")
You really, really should be storing this in a database. If you're building a website, you need a database anyway. ANYTHING related to application state should be stored in the database.
ALSO, this really, really shouldn't be happening server-side. Are you really performing a postback every time someone clicks anywhere on a page? If so, you have JavaScript in place to handle that, so just skip this insanity, have said script fire off an AJAX request, and have the target handler log it in the database.
Looks like your using a web site so presuming ASP.net. There are a number of ways to store the information. Database could be one or a persistent cookie could be the way to do it. See this article on how to create cookies: How do I set/unset cookie with jQuery?
You can try save it in session and then it will stay until the session is time out(20 minutes) if you want it to long time just write it to file in known location and when you close the web write the value to the file and when the web is up again take the vakue from the file.

Get running session count from IIS for my hosted Asp.Net web site

I am hosting an Asp.Net website in IIS 6.0
We have to reset the session timeout in web.config
My client want me to reset it only if no session is running (no one is using the site).
We have not used Membership and SessionState is set to InProc
How I get to know if anybody using the site or any session is running.
I can't make change in source code or any other file except web.config in the hosted website.
I'm not great at PowerShell, so hopefully you can look up the proper syntax. But ...
One option is to run a Powershell script and check the count of the session like this:
UPDATE: Changed 'Sessions Total' to 'Sessions Active'
write-host Getting performance counters ...
$perfCounterString = "\asp.net applications(__total__)\sessions active"
$counter = get-counter -counter $perfCounterString
$rawValue = $counter.CounterSamples[0].CookedValue
write-host Session Count is $rawValue
if( $rawValue -gt 0)
{
write-host Session are active - will not stop IIS
exit
}
write-host Stopping IIS
stop-service "IISAdmin"
# Set values
$webConfig = "d:\web.config"
$newTimeout = "20"
# Open file and change value
$doc = new-object System.Xml.XmlDocument
$doc.Load($webConfig)
$doc.SelectSingleNode("//sessionState").timeout = $newTimeout
$doc.Save($webConfig)
write-host Starting IIS
start-service "IISAdmin"
write-host Done!
Save this on the desktop as "ChangeIIS.ps1".
Now Powershell doesn't like you just running scripts like .bat files. You have to grant access to the process or your user for security reasons. So do the following:
Open a command prompt and Run As Administrator
Type powershell
Type Set-ExecutionPolicy -scope process Bypass
Type sl <path to directory of .sp1 file> . sl [set-location] is like cd in command prompt
Type $ '.\ChangeIIS.ps1'
It will run now and reset the value.
Here is a link to my blog on how I created the PowerShell script
in a more Step-by-step fashion
Check the IIS log files for your site and see when the last hit was made (by actual users, rather than search bots).
If the last hit was older than the current session timeout, then no active sessions exist. That is what you are actually looking for, rather than a count.
No programming or hacks required.
Hey Session timeout its not execuate if some one is using site..
so no need to worry
(The Timeout property specifies the time-out period assigned to the Session object for the application, in minutes. If the user does not refresh or request a page within the time-out period, the session ends.
)
Session WIth IIS
http://msdn.microsoft.com/en-us/library/ms525473(v=vs.90).aspx
Session with Config File
http://msdn.microsoft.com/en-us/library/ms178586.aspx
I think the simple answer here is "not possible".. You live you learn, see answer on ASP.NET Performance counters. I'm very interested on how that goes (if it works for you), and if it gives you application specific data (vs. aggregate of all applications on the box?).
Even the suggestion to look at log files will not get you what you want - as you're looking at the log file, how would you know there isn't a user starting a session?
Sessions are cookies to a browser. So if visit 1 page in your web site, I leave your website and go to some other web site, and then come back (before whatever timeout value you set)? How would you define that? At the point I left your web site, you will not see "any" activity (whatever monitor you use), but that doesn't mean my session is "expired".
It doesn't even have to be that complicated - I visit your web site, and start reading your content (not navigating, not doing anything that can be measure/monitored).
I guess there's more clarity needed on the "goal" - as in what are you after? The objective of resetting isn't the real "goal" of what you want to achieve.
Update:
I know you said you can't modify the source code, so you can hope that it implements Google Analytics. If so, you can look at the real time activity of your web site. This at least gets you "somewhere" in some trivial fashion. BUT just the same, the "magic" is based on cookies (which therefore means its still subject to the questions I posed above)
Keep increesing and decreesing an application variable at session start and session end events. then you will have the session count. if sesson count is zero, then you can reset the thing. all the best.

Limiting the scope of a NamedPipeServerStream

I would like to use NamedPipeServerStream to do some small IPC between instances of an app. However I only want to target the server if it is on the same Terminal Server Session as the client (If the app is run in a TS-environment).
An idea to achieve this would be to use the SID of the logon user and concat this with the Pipes name. Hover I think this will give problems if the user is loged on from two different locations and it also seems not very neat to me.
Is there a possiblity to give NamedPipeServerStream a scope in which it responds to calls and to set this scope so that the RDP-Session builds the border? Or has someone a good idea how to limit the scope/achieve the desired behaviour?
If you want to limit it to one session only you can create a named mutex within the local namespace to limit its visibility within your session. When a client wants to connect
it can create the same mutex and if it gets as last error code ERROR_ALREADY_EXISTS back it knows that within the current session a pipe server is.
You can get the current session number of your process via ProcessIdToSessionId so you can create a named pipe server with the session id in its name.
[DllImport("kernel32.dll",SetLastError=true)]
static extern int ProcessIdToSessionId(int pid, ref int session);
Addenum:
To get your current Session Id you can simply use Process.GetCurrentProcess().SessionId instead of the PInvoke signature defined above.

Set service dependencies after install

I have an application that runs as a Windows service. It stores various things settings in a database that are looked up when the service starts. I built the service to support various types of databases (SQL Server, Oracle, MySQL, etc). Often times end users choose to configure the software to use SQL Server (they can simply modify a config file with the connection string and restart the service). The problem is that when their machine boots up, often times SQL Server is started after my service so my service errors out on start up because it can't connect to the database. I know that I can specify dependencies for my service to help guide the Windows service manager to start the appropriate services before mine. However, I don't know what services to depend upon at install time (when my service is registered) since the user can change databases later on.
So my question is: is there a way for the user to manually indicate the service dependencies based on the database that they are using? If not, what is the proper design approach that I should be taking? I've thought about trying to do something like wait 30 seconds after my service starts up before connecting to the database but this seems really flaky for various reasons. I've also considered trying to "lazily" connect to the database; the problem is that I need a connection immediately upon start up since the database contains various pieces of vital info that my service needs when it first starts. Any ideas?
Dennis
what your looking for is SC.exe. This is a command line tool that users can use to configure services.
sc [Servername] Command Servicename [Optionname= Optionvalue...]
more specificly you would want to use
sc [ServerName] config ServiceName depend=servicetoDependOn
Here is a link on the commandlike options for SC.EXE
http://msdn.microsoft.com/en-us/library/ms810435.aspx
A possible (far from ideal) code solution:
In you startup method code it as a loop that terminates when you've got a connection. Then in that loop trap any database connection errors and keep retrying as the following pseudo code illustrates:
bool connected = false;
while (!connected)
{
try
{
connected = openDatabase(...);
}
catch (connection error)
{
// It might be worth waiting for some time here
}
}
This means that your program doesn't continue until it has a connection. However, it could also mean that your program never gets out of this loop, so you'd need some way of terminating it - either manually or after a certain number of tries.
As you need your service to start in a reasonable time, this code can't go in the main initialisation. You have to arrange for your program to "start" successfully, but not do any processing until this method had returned connected = true. You might achieve this by putting this code in a thread and then starting your actual application code on the "thread completed" event.
Not a direct answer put some points you can look into
Windows service can be started Automatically with a delay. You can check this question in SO for some information about it.
How to make Windows Service start as “Automatic (Delayed Start)”
Check this post How to: Code Service Dependencies

Categories

Resources