Is there an event fired when screensaver starts? Like for keychain locking:
OSStatus keychain_locked(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void *context){...}
Finally found it — the solution is to use NSDistributedNotificationCenter and observe folowing events
com.apple.screensaver.didstart
com.apple.screensaver.willstop
com.apple.screensaver.didstop
com.apple.screenIsLocked
com.apple.screenIsUnlocked
Like
[[NSDistributedNotificationCenter defaultCenter]
addObserver:self
selector:#selector(screensaverStarted:)
name:#"com.apple.screensaver.didstart"
object:nil];
While there is no Carbon event for this, you can get notified when the current application changes, and then check to see if the new application is the screen saver process.
// Register the event handler for when applications change
{
EventTypeSpec es;
es.eventClass = kEventClassApplication;
es.eventKind = kEventAppFrontSwitched;
InstallApplicationEventHandler(&appChanged, 1, &es, NULL, NULL);
}
OSStatus appChanged(EventHandlerCallRef nextHandler, EventRef anEvent, void* userData)
{
ProcessSerialNumber psn;
GetEventParameter(anEvent, kEventParamProcessID, typeProcessSerialNumber,
NULL, sizeof(psn), NULL, &psn);
// Determine process name
char procName[255];
{
ProcessInfoRec pInfo;
Str255 procName255;
FSRef ref;
pInfo.processInfoLength = sizeof(ProcessInfoRec);
pInfo.processName = procName255;
pInfo.processAppRef = &ref;
GetProcessInformation(&psn, &pInfo);
const unsigned int size = (unsigned int)procName255[0];
memcpy(procName, procName255 + 1, size);
procName[size] = '\0';
}
if(strcmp(procName, "ScreenSaverEngine") == 0)
{
NSLog(#"Found %s\n", procName);
}
return noErr;
}
This isn't exactly an answer to the question, but I spent a lot of time looking in vain for a list of the notifications posted by macOS, so I wanted to post some code I wrote for notification discovery.
The code simply signs up to listen to all notifications, and prints some info for each as it comes in.
import Foundation
let distCenter = CFNotificationCenterGetDistributedCenter()
if distCenter == nil {
exit(1)
}
CFNotificationCenterAddObserver(distCenter, nil, { (center, observer, name, object, userInfo) -> Void in
print("Event occurred: \(name) User info: \(userInfo)")
}, nil, nil, .DeliverImmediately)
CFRunLoopRun()
Related
I'm writing some networking code in Swift that prevents initiating a download that is already in progress. I do this by keeping tracking of the identity of the network request along with the associated completion handlers in an (synchronized) array A. When a network call finishes it calls the completion handlers that are associated with that resource and it subsequently removes those handlers from the array A.
I want to make sure there is no way for threads to access the array in certain cases. For example, consider the following scenario:
A request to download resource X is started.
Verify whether the request has already been made.
Add the completion handler to the array A.
If request has not been made, start the download.
What if resource X was already downloading, and the completion handler for this download interrupts the thread between steps 2 and 3? It has been verified that the request has been made so the download will not be started, but the new completion handler will be added to array A which will now never be called.
How would I block this from happening? Can I lock the array for writing while I do steps 2 and 3?
The simple solution is to run everything on the main thread except the actual downloading. All you need to do is make the completion handler a stub that places a block on the main queue to do all the work.
The pseudo code for what you want is something like
assert(Thread.current == Thread.main)
handlerArray.append(myHandler)
if !requestAlreadyRunning)
{
requestAlreadyRunning = true
startDownloadRequest(completionHandelr: {
whatever in
Dispatch.main.async // This is the only line of code that does not run on the main thread
{
for handler in handlerArray
{
handler()
}
handlerArray = []
requestAlreadyRunning = false
}
})
}
This works because all the work that might result in race conditions and synchronisation conflicts runs on one thread - the main thread and so the completion handler can't possibly be running when you are adding new completion handlers to the queue and vice versa.
Note that, for the above solution to work, your application needs to be in a run loop. This will be true for any Cocoa based application on Mac OS or iOS but not necessarily true for a command line tool. If that is the case or if you don't want any of the work to happen on the main thread, set up a serial queue and run the connection initiation and the completion handler on it instead of the main queue.
I'm working on the assumption that you want to be able to add multiple callbacks that will all be run when the latest request completes, whether it was already in-flight or not.
Here's a sketch of a solution. The basic point is to take a lock before touching the array(s) of handlers, whether to add one or to invoke them after the request has completed. You must also synchronize the determination of whether to start a new request, with the exact same lock.
If the lock is already held in the public method where the handlers are added, and the request's own completion runs, then the latter must wait for the former, and you will have deterministic behavior (the new handler will be invoked).
class WhateverRequester
{
typealias SuccessHandler = (Whatever) -> Void
typealias FailureHandler = (Error) -> Void
private var successHandlers: [SuccessHandler] = []
private var failureHandlers: [FailureHandler] = []
private let mutex = // Your favorite locking mechanism here.
/** Flag indicating whether there's something in flight */
private var isIdle: Bool = true
func requestWhatever(succeed: #escaping SuccessHandler,
fail: #escaping FailureHandler)
{
self.mutex.lock()
defer { self.mutex.unlock() }
self.successHandlers.append(succeed)
self.failureHandlers.append(fail)
// Nothing to do, unlock and wait for request to finish
guard self.isIdle else { return }
self.isIdle = false
self.enqueueRequest()
}
private func enqueueRequest()
{
// Make a request however you do, with callbacks to the methods below
}
private func requestDidSucceed(whatever: Whatever)
{
// Synchronize again before touching the list of handlers and the flag
self.mutex.lock()
defer { self.mutex.unlock() }
for handler in self.successHandlers {
handler(whatever)
}
self.successHandlers = []
self.failureHandlers = []
self.isIdle = true
}
private func requestDidFail(error: Error)
{
// As the "did succeed" method, but call failure handlers
// Again, lock before touching the arrays and idle flag.
}
}
This is so broadly applicable that you can actually extract the callback storage, locking, and invocation into its own generic component, which a "Requester" type can create, own, and use.
Based on Josh's answer I created a generic Request & Requester below. It had a few more specific needs than I described in the question above. I want the Request instance to manage only requests with a certain ID (which I made into a String for now, but I guess this could also made more generic). Different ID's require a different Request instance. I created the Requester class for this purpose.
The requester class manages an array of Requests. For example, one could choose T = UIImage, and ID = image URL. This would give us an image downloader. Or one could choose T = User, and ID = user id. This would get a user object only once, even when requested several times.
I also wanted to be able to cancel requests from individual callers. It tags the completion handler with a unique ID that is passed back to the caller. It can use this to cancel the request. If all callers cancel, the request is removed from the Requester.
(The code below has not been tested so I cannot guarantee it to be bug free. Use at your own risk.)
import Foundation
typealias RequestWork<T> = (Request<T>) -> ()
typealias RequestCompletionHandler<T> = (Result<T>) -> ()
typealias RequestCompletedCallback<T> = (Request<T>) -> ()
struct UniqueID {
private static var ID: Int = 0
static func getID() -> Int {
ID = ID + 1
return ID
}
}
enum RequestError: Error {
case canceled
}
enum Result<T> {
case success(T)
case failure(Error)
}
protocol CancelableOperation: class {
func cancel()
}
final class Request<T> {
private lazy var completionHandlers = [(invokerID: Int,
completion: RequestCompletionHandler<T>)]()
private let mutex = NSLock()
// To inform requester the request has finished
private let completedCallback: RequestCompletedCallback<T>!
private var isIdle = true
// After work is executed, operation should be set so the request can be
// canceled if possible
var operation: CancelableOperation?
let ID: String!
init(ID: String,
completedCallback: #escaping RequestCompletedCallback<T>) {
self.ID = ID
self.completedCallback = completedCallback
}
// Cancel the request for a single invoker and it invokes the competion
// handler with a cancel error. If the only remaining invoker cancels, the
// request will attempt to cancel
// the associated operation.
func cancel(invokerID: Int) {
self.mutex.lock()
defer { self.mutex.unlock() }
if let index = self.completionHandlers.index(where: { $0.invokerID == invokerID }) {
self.completionHandlers[index].completion(Result.failure(RequestError.canceled))
self.completionHandlers.remove(at: index)
if self.completionHandlers.isEmpty {
self.isIdle = true
operation?.cancel()
self.completedCallback(self)
}
}
}
// Request work to be done. It will only be done if it hasn't been done yet.
// The work block should set the operation on this request if possible. The
// work block should call requestFinished(result:) if the work has finished.
func request(work: #escaping RequestWork<T>,
completion: #escaping RequestCompletionHandler<T>) -> Int {
self.mutex.lock()
defer { self.mutex.unlock() }
let ID = UniqueID.getID()
self.completionHandlers.append((invokerID: ID, completion: completion))
guard self.isIdle else { return ID }
work(self)
self.isIdle = false
return ID
}
// This method should be called from the work block when the work has
// completed. It will pass the result to all completion handlers and call
// the Requester class to inform that this request has finished.
func requestFinished(result: Result<T>) {
self.mutex.lock()
defer { self.mutex.unlock() }
completionHandlers.forEach { $0.completion(result) }
completionHandlers = []
self.completedCallback(self)
self.isIdle = true
}
}
final class Requester<T> {
private lazy var requests = [Request<T>]()
private let mutex = NSLock()
init() { }
// reuqestFinished(request:) should be called after a single Request has
// finished its work. It removes the requests from the array of requests.
func requestFinished(request: Request<T>) {
self.mutex.lock()
defer { self.mutex.unlock() }
if let index = requests.index(where: { $0.ID == request.ID }) {
requests.remove(at: index)
}
}
// request(ID:, work:) will create a request or add a completion handler to
// an existing request if a request with the supplied ID already exists.
// When a request is created, it passes a closure that removes the request.
// It returns the invoker ID to the invoker for cancelation purposes.
func request(ID: String,
work: #escaping RequestWork<T>,
completion: #escaping RequestCompletionHandler<T>) ->
(Int, Request<T>) {
self.mutex.lock()
defer { self.mutex.unlock() }
if let existingRequest = requests.first(where: { $0.ID == ID }) {
let invokerID = existingRequest.request(work: work, completion: completion)
return (invokerID, existingRequest)
} else {
let request = Request<T>(ID: ID) { [weak self] (request) in
self?.requestFinished(request: request)
}
let invokerID = request.request(work: work, completion: completion)
return (invokerID, request)
}
}
}
I'm studying how to implement key event capturing and callback for a OSX no-GUI command-line tool within its process space, in C, using CoreFoundation only, (no Cocoa, no NSEvents). Upon some research, I could easily put together this MCVE on "global level" (which requires running the program with root privileges), but could not figure out what to do for capturing and processing key events in the program's process space only. I also haven't found documentation on how this can be done. I have found some questions from this area on SO, but all of them were Cocoa API based. I'll gladly provide any additional information needed.
// gcc -Wall -o test test.c -framework ApplicationServices
// sudo test
#include <ApplicationServices/ApplicationServices.h>
CGEventRef testEventCallback(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void *refcon)
{
printf( " Event Type: %d\n", type );
return event;
}
int main(int argc, char *argv[])
{
CFMachPortRef eventPort;
CFRunLoopSourceRef eventSrc;
CFRunLoopRef runLoop;
CGEventMask mask = CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp);
eventPort = CGEventTapCreate(kCGSessionEventTap,
kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly,
mask,
testEventCallback,
NULL );
if ( eventPort == NULL ){
printf( "NULL eventPort\n" );
return 1;
}
eventSrc = CFMachPortCreateRunLoopSource(NULL, eventPort, 0);
if ( eventSrc == NULL ){
printf( "NULL eventSrc\n" );
return 1;
}
runLoop = CFRunLoopGetCurrent();
if ( runLoop == NULL ){
printf( "NULL runLoop\n" );
return 1;
}
CFRunLoopAddSource(runLoop, eventSrc, kCFRunLoopDefaultMode);
CFRunLoopRun();
return 0;
}
Here's some code that works from a Swift command line tool running in Terminal. It taps the events that would normally be routed to Terminal.app, or whatever process was frontmost when the tool began running. It avoids consuming command keys so you can easily terminate the program with command-period if you need to. Since GetFrontProcess() is now deprecated, it uses NSWorkspace to locate the front process.
let lock = DispatchQueue(label: "lock")
var events = [CGEvent]()
// track keyboard events using an event tap.
let callback: CGEventTapCallBack = { (tapProxy, eventType, event, _) -> Unmanaged<CGEvent>? in
// don't consume command keys.
if !event.flags.contains(.maskCommand) {
if eventType == .keyDown {
lock.sync {
events.append(event)
}
}
return nil
}
return Unmanaged<CGEvent>.passUnretained(event)
}
let eventMask = CGEventMask((1 << CGEventType.keyDown.rawValue) | (1 << CGEventType.keyUp.rawValue))
if let frontmostProcess = NSWorkspace.shared.frontmostApplication?.processIdentifier, let eventTap = CGEvent.tapCreateForPid(pid: frontmostProcess, place: .headInsertEventTap, options: .defaultTap, eventsOfInterest: eventMask, callback: callback, userInfo: nil) {
let source = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0)
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, .commonModes)
CGEvent.tapEnable(tap: eventTap, enable: true)
CFRunLoopRun()
}
I was working on writing a screenshot thing, and found this excellent topic for Mac: How can I get screenshot from all displays on MAC?
I was wondering if anyone has the equivalent for x11 library? To get all the monitors and then screenshot them all?
I had found this topic: https://stackoverflow.com/a/5293559/1828637
But the code linked from there is not as easy to follow for a novice like me.
Will RootWindow(3) get the area of all the monitors combined? Then I can go through and get the monitors dimensions then XGetImage those sections on the return of RootWindow?
I had come across this topic: How do take a screenshot correctly with xlib? But I'm not sure if it has multi-monitor support. I do this in ctypes so I cant test that code easily without going through the grueling task of writing it first. So I was wondering if this is correct or how would I modify it to handle multi mon please?
Edit
The poster there shared his code, it is seen here: https://github.com/Lalaland/ScreenCap/blob/master/src/screenCapturerImpl.cpp#L96 but it's complicated and I don't understand it. It uses functions like XFixesGetCursorImage which I can't find in the documentation, and I don't see how the multi monitors work there. Author of that topic warned he doesn't remember the code and it may not work with modern Linux.
This is not a perfect answer to the question, but the following code could be modified to get a very fast version of your desired end result:
https://github.com/Clodo76/vr-desktop-mirror/blob/master/DesktopCapture/main.cpp
The DesktopCapturePlugin_Initialize method converts all the displays into objects:
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API DesktopCapturePlugin_Initialize()
{
DesksClean();
g_needReinit = 0;
IDXGIFactory1* factory;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory));
IDXGIAdapter1* adapter;
for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i)
{
IDXGIOutput* output;
for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); j++)
{
DXGI_OUTPUT_DESC outputDesc;
output->GetDesc(&outputDesc);
MONITORINFOEX monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(outputDesc.Monitor, &monitorInfo);
// Maybe in future add a function to identify the primary monitor.
//if (monitorInfo.dwFlags == MONITORINFOF_PRIMARY)
{
int iDesk = DeskAdd();
g_desks[iDesk].g_width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
g_desks[iDesk].g_height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
IDXGIOutput1* output1;
output1 = reinterpret_cast<IDXGIOutput1*>(output);
output1->DuplicateOutput(device, &g_desks[iDesk].g_deskDupl);
}
output->Release();
}
adapter->Release();
}
factory->Release();
}
Then the OnRenderEvent method copies a frame from the display into a texture (provided by unity in this case):
void UNITY_INTERFACE_API OnRenderEvent(int eventId)
{
for (int iDesk = 0; iDesk < g_nDesks; iDesk++)
{
if (g_desks[iDesk].g_deskDupl == nullptr || g_desks[iDesk].g_texture == nullptr)
{
g_needReinit++;
return;
}
IDXGIResource* resource = nullptr;
const UINT timeout = 0; // ms
HRESULT resultAcquire = g_desks[iDesk].g_deskDupl->AcquireNextFrame(timeout, &g_desks[iDesk].g_frameInfo, &resource);
if (resultAcquire != S_OK)
{
g_needReinit++;
return;
}
g_desks[iDesk].g_isPointerVisible = (g_desks[iDesk].g_frameInfo.PointerPosition.Visible == TRUE);
g_desks[iDesk].g_pointerX = g_desks[iDesk].g_frameInfo.PointerPosition.Position.x;
g_desks[iDesk].g_pointerY = g_desks[iDesk].g_frameInfo.PointerPosition.Position.y;
ID3D11Texture2D* texture;
HRESULT resultQuery = resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture));
resource->Release();
if (resultQuery != S_OK)
{
g_needReinit++;
return;
}
ID3D11DeviceContext* context;
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
device->GetImmediateContext(&context);
context->CopyResource(g_desks[iDesk].g_texture, texture);
g_desks[iDesk].g_deskDupl->ReleaseFrame();
}
g_needReinit = 0;
}
Thanks to the updates to GameKit API in iOS 6, I am finally able to implement my turn-based board game the way it should be, complete with turn timeouts and better programmatic creation of matches. However, I am running into an issue that I cannot seem to solve. My desire is to have Game Center running entirely invisible to the end-user, so that everything is programmatic and uses my own custom interfaces. Therefore, I use my own custom table view to display matches, not the default GKTurnBasedMatchmakerViewController. Right now, I have no problem displaying open matches using the -loadMatchesWithCompletionHandler: method. I also use a custom screen to create a match, with a direct creation for auto-match (not a problem) and a table view that loads Game Center friends of the localPlayer for invitation. Since the playersToInvite attribute can now be filled with playerID's, this is possible in iOS 6.
My main problem is handling the invitation on the recipient's side. I send the invitation with the following code
-(void)invitarAmigoMio:(NSArray*)losAmigos
{
GKMatchRequest *request = [[GKMatchRequest alloc] init];
request.minPlayers = 2;
request.maxPlayers = 2;
request.defaultNumberOfPlayers=2;
request.playersToInvite = losAmigos;
request.inviteMessage = #"Your Custom Invitation Message Here";
request.inviteeResponseHandler = ^(NSString *playerID, GKInviteeResponse
response)
{
if (response==GKInviteeResponseAccepted)
{
NSLog(#"INVITACION ACEPTADA");
}
else
{
NSLog(#"INVITACION RECHAZADA");
}
};
}
I have a delegate that handles the notifications. The following code is launch when the user is authenticated
-(void)registroNotificaciones
{
NSLog(#"registroNotificaciones");
[GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite* acceptedInvite, NSArray *playersToInvite)
{
if(acceptedInvite != nil)
{
// Get a match for the invite we obtained...
[[GKMatchmaker sharedMatchmaker] matchForInvite:acceptedInvite completionHandler:^(GKMatch *match, NSError *error)
{
if(match != nil)
{
NSLog(#"match != nil: ");
}
else if(error != nil)
{
NSLog(#"ERROR: From matchForInvite: %#", [error description]);
}
else
{
NSLog(#"ERROR: Unexpected return from matchForInvite...");
}
}];
}
};
NSLog(#"FIN registroNotificaciones");
}
Why notifications are not send?Or notifications are not received?Is there another way to send notification to invite to play a game?
I checked and my sandbox accounts of Game Center allow invitations, and I dont know what´s going on
You did pretty much all that is needed to create the invite; you just need to send it with this code:
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request withCompletionHandler:^(GKMatch* match, NSError *error) {
if (error)
{
//Invite has not been sent
}
else if (match != nil)
{
//whatever you want to do when the receiver accepts the invite
}
}];
I know you are looking to use custom displays but I haven't made my own view controllers for this, instead I used GKMatchmakerViewController which handles the 'send' invites for me and I think that's what's missing in your code.
Here is my code for that, maybe you can try it and check how GKMatchmakerViewController works internally (if possible):
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = minPlayers;
request.maxPlayers = maxPlayers;
request.playersToInvite = pendingPlayersToInvite;
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = self;
[myPresentingViewController presentModalViewController:mmvc animated:YES];
I have almost the same code you have that handles the notifications (registroNotificaciones) and it gets executed as soon as the user authenticates with GameCenter and is one of the first things the app does when launched too, from what you say, it looks like this code is working properly, just . Hope it helps!
I am looking for a Win32 API call to return the runtime context of my process. I want to be able to programmatically test if I am running as a service or am I running as standard application process.
Several ideas come to mind.... Since I always have service DAD.exe who runs SON.exe sometimes as his child and in service context --- and sometimes SON.exe is started not by DAD, and by a user.
SON.EXE would do API whoami() to learn which context he is running in.
Now DAD could create an environment var -- and then SON could test for this var -- and if found he knows he is a son of DAD and thus runnning as a service..... But this is weak...
Another idea would be to look at my SID or token and see if I could make this determination.... Again this looks at best more complex vs. a single API check...
The simple low-tech solution to this is to register your service to run with command line arguments that identify it as a service.
Another option is to use the Tool Help library. Using it, you take a snapshot of all the currently running processes and then you can walk through all the processes using the Process32First and Process32Next function. These return a structure (PROCESSENTRY32) that looks like:
typedef struct tagPROCESSENTRY32 {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
TCHAR szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32;
as you walk through all the processes, as soon as you find the one whose th32ProcessID matches the one for SON.exe (see GetCurrentProcessId or GetProcessId ). If the th32ParentProcessID of that structure matches that of DAD.exe, then you know you were launched from DAD.exe.
Edit:
Answering your comment, I guess you could go one step further and then see who the parent of DAD.exe is, if it's services.exe, then you're a service.
Reading the documentation, I think you could determine whether you're in an interactive session or service via:
GetProcessWindowStation
GetUserObjectInformation(UOI_FLAGS)
and then WSF_VISIBLE should tell you.
If you wanted to differentiate between a logged-in user session and one that's inactive (Fast User Switching), I guess you could use GetThreadDesktop and GetUserObjectInformation(UOI_IO).
The best and simplest way to tell from inside the service is to set a flag when ServiceMain is called. But you're testing a child process, so see above.
I found the following:
bool WinUtil::IsServiceUser(HANDLE hToken, bool *is_service) {
if (is_service == NULL) {
return false;
}
TOKEN_STATISTICS ts;
DWORD dwSize = 0;
// Use token logon LUID instead of user SID, for brevity and safety
if (!::GetTokenInformation(hToken, TokenStatistics,
(LPVOID)&ts, sizeof(ts), &dwSize)) {
return false;
}
// Compare LUID
const LUID SystemLuid = SYSTEM_LUID;
const LUID LocalServiceLuid = LOCALSERVICE_LUID;
const LUID NetworkServiceLuid = NETWORKSERVICE_LUID;
if (EqualLuid(SystemLuid, ts.AuthenticationId) ||
EqualLuid(LocalServiceLuid, ts.AuthenticationId) ||
EqualLuid(NetworkServiceLuid, ts.AuthenticationId)) {
*is_service = true;
return true;
}
// Not a service account
*is_service = false;
return true;
}
bool WinUtil::IsServiceProcess(bool *is_service) {
if (is_service == NULL) {
return false;
}
if (Util::IsVistaOrLater()) {
// Session 0 is dedicated to services
DWORD dwSessionId = 0;
if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &dwSessionId) ||
(dwSessionId == 0)) {
*is_service = true;
return true;
}
}
// Get process token
HANDLE hProcessToken = NULL;
if (!::OpenProcessToken(::GetCurrentProcess(),
TOKEN_QUERY | TOKEN_QUERY_SOURCE,
&hProcessToken)) {
return false;
}
ScopedHandle process_token(hProcessToken);
// Process token is one for a service account.
if (!IsServiceUser(process_token.get(), is_service)) {
return false;
}
return true;
}
I think your looking for Topshelf http://topshelf-project.com/, it does the heavy lifting and makes it easier run as console or install as a service. Topshelf hosting application debugging in VS2010