Is there anyway to know which user is calling the WCF Ria service on server side, using silverlight on clientside? - silverlight

Is there anyway to know which user is calling the WCF Ria service on server side? Client side is siverlight, user has to be authenticated first in order to use the system.
I need to know which user is actually calling the service in my current task, thanks, i searched a lot, but seems no good findings.

Once the client side has successfully cleared your authentication challenge, the server can issue a token to the caller on the client side. In subsequent calls to the server, the client would send the token as one of the arguments and the server would verify the token and respond accordingly.
The token can contain a segment of information that identifies a given user, and implementing this will provide the functionality you are seeking.
The only guidelines for generating tokens is that they are unique, non-predictable and expirable. I have always encrypted my tokens so that they appear as gibberish, but step this is optional.

I've also done very much "googleing" and got a lot of headache before I got the solution.
I don't use RIA-Services - but it should be (hopefully) the same...:
The SL-Client sends a "login-request" to the server.
On the (WCF) server-side, I do the following (LoginData = Return-Info for SL-Client):
public LoginData LoginRequest() {
(...)
OperationContext context = OperationContext.Current;
System.ServiceModel.Channels.MessageProperties prp = context.IncomingMessageProperties;
System.ServiceModel.Channels.RemoteEndpointMessageProperty endPrp = prp[System.ServiceModel.Channels.RemoteEndpointMessageProperty.Name] as System.ServiceModel.Channels.RemoteEndpointMessageProperty;
(...)
try {
clientIP = endPrp.Address;
System.Net.IPAddress ipAddress = System.Net.IPAddress.Parse(clientIP);
System.Net.IPHostEntry ipHostEntry = System.Net.Dns.GetHostEntry(ipAddress);
(...)
If you want to check the users WindowsPrincipal, you can do the following (securityGroup = server-side setting, which users can login):
(...)
switch (securityGroup) {
case SecurityGroup.AllClientsCanAccess: {
clientCanLogin = true;
} break;
case SecurityGroup.UseWindowsCredentials: {
if (OperationContext.Current.ServiceSecurityContext != null && OperationContext.Current.ServiceSecurityContext.WindowsIdentity != null) {
if (OperationContext.Current.ServiceSecurityContext.WindowsIdentity.IsAuthenticated) {
if (subSecurityInfo1 == true) { // only clients in specific roles can log in
bool userRoleFound = false;
WindowsPrincipal userPrincipal = new WindowsPrincipal(OperationContext.Current.ServiceSecurityContext.WindowsIdentity);
if (userPrincipal == null)
break;
foreach (string userRoleToPass in subSecurityList) { // subSecurityList = settings, which roles can pass
loginError.ErrorInfo += string.Format("{0}\n", userRoleToPass);
if (userPrincipal.IsInRole(userRoleToPass)) {
clientCanLogin = userRoleFound = true;
break;
}
}
if (userRoleFound) {
loginError.ErrorInfo = string.Empty;
break;
}
else {
loginError.ErrorNo = LoginErrorCodeNoEnum.UserIsNotInRole;
}
}
(...)
Hope it helps...

Related

Loading a new window from local files and accessing it's contents

I am setting up a local webpage which shows videos in a HTML5 video tag. I just want to be able to do database search from a PHP request and show the results from which I can click on and show the video I want. The problem I have is that hte videos load WAY faster when loading from a "file:///" link than from the "http://" link. Server works flawlessly when in "HTTP" mode but nothing works in "file:///" mode which is normal as PHP codes only execute on the server side when requested to the server.
I have spent my full day trying soo much stuff. I changed my server to accept CORS, I tried window.open, storing the reference in a variable, local or global but I lose this as soon as I get out of my javascript function. I tried window.open in a function which is called from another function but no matter what I do, the window reference gets lost as soon as I leave the functions, or once the functions have finished. Since my browser is used as my main browser, I do not want to disable the security arround CORS but since my webpage's link comes from "file:///" requesting to "HTTP" on the same computer, CORS blocks me and wants an HTTP request which I can't give.
I have done all the searching for retrieving information from another webpage but I am always stuck with the "same domain" problem. I tried AJAX HTTPRequest, I just have no more solution for this simple problem which finished way more complicated than expected. The initial problem was just my videos not loading fast enough in HTTP mode (The speed difference is extreme, for 10 min videos, I can wait 5-10 seconds to skip through it while as in FILE:/// urls, It's almost instant, no waiting. longer videos of 1h, I can wait up to 20 and 30 seconds while as in file:/// mode, almost instant.) and I had to learn all that Allow cross domains stuff which ended up with no success either. I figure that maybe a few other heads may have better ideas than mine now.
#In my httpd.conf file from Apache
DocumentRoot "e:/mainwebfolder"
Alias "/lp" "d:/whatever"
//////////////////////////////////////
// index.php file that does not contain PHP contents
// window.location.href: file://d:/whatever/index.php
//////////////////////////////////////
<head>
<script src="html/servcom.js" type="text/javascript"></script>
</head>
<video id="vplayer" width="1280" height="720" controls></video>
<div id="search-form">
<input id="srch" name="srch" type="text">
<button class="bbut" onclick="ServInfo('search-results','http://127.0.0.1/lp/html/db.php','mode=s','search-form');">Search</button>
</div>
<div id='search-results'></div>
<script>
var dplay = document.getElementById("vplayer");
ShowVideo('MyVideo.mp4');
function ShowVideo (vidUrl) {
dplay = document.getElementById("vplayer");
dplay.src = vidUrl;
dplay.load;
}
</script>
//////////////////////////////////////
// Now this is in my javascript file servcom.js
//////////////////////////////////////
var win_ref = -1;
function ServInfo(pop_field_id,web_page,params="",form_id="",exec_string = "") {
var sparams = params;
var swpage = web_page;
var eobj = document.getElementById(pop_field_id);
var moreparams = "";
// If we entered extra parameters including form fields,
// add the the "&" before the form field list
if (sparams != "") {moreparams = "&";}
// Get form field values if a form id is specified
if (form_id != "") {
var efrm = document.getElementById(form_id);
sparams += moreparams+GetDivFields(form_id);
}
// Add the question mark if there is any parameters to pass
if (sparams != "") {
sparams = "?"+sparams;
// Add recieving objects reference
sparams += "&srco="+pop_field_id;
}
// If HTML element to populate does not exist, exit
if (typeof(eobj) == "!undefined" || eobj == null) {return;}
win_ref = window.open(swpage+sparams,"_blank");
//////////////////////////////////////
// right here win_ref will never be available once the code from this function has been finished executing although the variable is global. The problem starts here.
//////////////////////////////////////
// Execute a string if a user defined one
if (exec_string != "") {eval(exec_string);}
}
// Build a parameter string with div fields of type text, hidden or password
function GetDivFields(div_id) {
var ediv = document.getElementById(div_id);
var elem = ediv.children;
var retval = "";
var ssep = "";
for (var i = 0; i < elem.length; i++) {
if (elem[i].type == "text" || elem[i].type == "hidden" || elem[i].type == "password") {
retval += ssep+elem[i].name+"="+pURL(elem[i].value);
ssep = "&";
}
if (elem[i].type == "checkbox") {
if (elem[i].checked == true) {
retval += ssep+elem[i].name+"="+elem[i].value;
ssep = "&";
}
}
}
return retval;
}
//////////////////////////////////////
// And this is a brief overview of my db.php page
//////////////////////////////////////
<?php // Search Database code ?>
<div id="output"></div>
<script>
document.getElementById('output').innerHTML = "<?php echo $search_results; ?>";
// I actually want to retrieve the info from this div element once it has been populated from the initial page that called window.open for this page. BUT again. window.opener becomes empty once my initial window.open script finishes.
</script>
Access my newly loaded page's "output" div innerHTML OR loading videos through local HTTP as fast as "FILE:///".
Well, I fanally found a solution. Since this is for local and presentation use only, I could bypass some securities. Basically, doing what we would normally NOT do in a website but all this WITHOUT modifying your webserver config or touching any .htaccess file. Basically, no security restrictions, just a plain old hack that poses no security breaches for your browser or your server.
To be noted:
2 different websites exist (so 2 different folders at very different locations), 1 for developpement and serious releases, one for internal and/or presentation purposes.
Every file is local abd inside the presentation folder.
No PHP code can be ran from a "file:///" link.
Access to the mysql database is done through PHP and server is on Apach24
Reading video locally from a "file:///" link are WAY faster than from an "http://" link
Searching needs to be done in MySQL database frm a "http://" link and results need to be displayed on a webpage opened from a "file:///" link.
No changes must be made in the Browser's configuration so disabling CORS is not a solution.
Bypassing cors with methods proposed by many site won't work because of security reasons or because CORS bypass does not accept "file:///" links
PHP can write files on the server which is where I decided to bypass CORS. Since XML requests through AJAX can be done on the same origin domain an thus, purely in javascript. If a file exists which contains no PHP code AND resides on the same domaine i/e "file:///", the contents can the be read wothout any problems.
So I simply do the following in my db.php file:
$s_mode = "";
$s_text = "";
$sres = "";
if (isset($_REQUEST["srch"])) {$s_text=$_REQUEST["srch"];}
if (isset($_REQUEST["mode"])) {$s_mode=$_REQUEST["mode"];}
if ($s_mode == "s") {
$sres = SearchDB($s_text);
WriteFile("D:/whatever/my_path/dbres.html",$sres);
}
// Writes the contents of the search in a specified file
function WriteFile($faddress,$fcontents) {
$ifile = fopen($faddress,"w");
fwrite($ifile,$fcontents);
fclose($ifile);
}
Now using a normal AJAX request, I do 2 things. I opted to use an iframe with a "display:none" style to not bother seeing another tab openup.
Do the actual request which opens the "cross-doamin" link in the iframe WHICH executes my db.php code. I basically open "http://127.0.0.1/whatever/db.php?param1=data&parma2=data" inside my iframe.
Once my search is done and I have the results, my db.php will save an html file with the results as it's contents in my "file:///" direct location's path so: "D:/whatever/my_path/dbres.html".
I added a new function in my servcom.js. So my new file's contents looks like this:
// Show page info in another page element or window with parameters (for local use only)
function ServInfoLocal(dest_frame,web_page,params="",form_id="") {
var sparams = params;
var swpage = web_page;
var iweb = document.getElementById(dest_frame);
var moreparams = "";
// If we entered extra parameters including form fields,
// add the the "&" before the form field list
if (sparams != "") {moreparams = "&";}
// Get form field values if a form id is specified
if (form_id != "") {
var efrm = document.getElementById(form_id);
sparams += moreparams+GetDivFields(form_id);
}
// If destination frame does not exist, exit
if (typeof(iweb) == "!undefined" || iweb == null) {return;}
// Add the question mark if there is any parameters to pass
if (sparams != "") {sparams = "?"+sparams;}
// Show results in iframe
iweb.src = swpage+sparams;
}
// AJAX simple HTTP GET request
function ServInfo(pop_field_id,web_page,params="",form_id="",append_data_to_output = "",exec_string = "",dont_show_results = "") {
var sparams = params;
var swpage = web_page;
var eobj = document.getElementById(pop_field_id);
var moreparams = "";
// If we entered extra parameters including form fields,
// add the the "&" before the form field list
if (sparams != "") {moreparams = "&";}
// Get form field values if a form id is specified
if (form_id != "") {
var efrm = document.getElementById(form_id);
sparams += moreparams+GetDivFields(form_id);
}
// If HTML element to populate does not exist, exit
if (typeof(eobj) == "!undefined" || eobj == null) {return;}
if (window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {
// IE6-
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Do not show any results if requested
if (dont_show_results == "") {
if (append_data_to_output == "y") {
document.getElementById(pop_field_id).innerHTML += this.responseText;
}
if (append_data_to_output == "") {
document.getElementById(pop_field_id).innerHTML = this.responseText;
}
}
// Execute a string if a user defined one
if (exec_string != "") {
eval(exec_string);
}
}
};
// Add the question mark if there is any parameters to pass
if (sparams != "") {swpage += "?";}
xmlhttp.open("GET",swpage+sparams,true);
xmlhttp.send();
}
// Build a parameter string with div fields of type text, hidden or password
function GetDivFields(div_id) {
var ediv = document.getElementById(div_id);
var elem = ediv.children;
var retval = "";
var ssep = "";
for (var i = 0; i < elem.length; i++) {
if (elem[i].type == "text" || elem[i].type == "hidden" || elem[i].type == "password") {
retval += ssep+elem[i].name+"="+pURL(elem[i].value);
ssep = "&";
}
if (elem[i].type == "checkbox") {
if (elem[i].checked == true) {
retval += ssep+elem[i].name+"="+elem[i].value;
ssep = "&";
}
}
}
return retval;
}
Now, my dbres.html file will contain just the div elements and all the information I need to show up in my "file:///" page from which the search request came from. So I simply have this inside my page:
<div id="search-form" style="color:white;font-weight:bold;">
<input id="srch" name="srch" type="text">
<button class="bbut" onclick="ServInfoLocal('iweb','http://127.0.0.1/whatever/html/db.php','mode=s','search-form');">Search</button>
<button class="bbut" onclick="ServInfo('search-results','dbres.html');">Click here</button>
</div>
<div id="search-results">Results here</div>
<iframe id="iweb" style="display:none;" src=""></iframe>
For now I have 2 buttons, one for the search and one to show the results from my newly created file. Now, I can show my local videos which will load in my video container with "file:///" source directly without passing through http. I'll make my results display automatic which I will be able to do myself from here on.
So, if someone on planet earth wants to be able to do cross-domain searches in a MySQL database from a local file ran directly from the Windows explorer, there's not too many solutions, actually, I found none so here is at least one for who would ever need this solution.
For the curious ones out there, my next step will be to loop my folder until my dbres file is present using another js function. Once my file has been fetched, call another php file which wil destroy the created file and I'll be ready for another database request from my webpage situated in a "file:///" location.

Firebase Unity - Get all children into an array/generic list after GetValueAsync?

How can I get data back as an array or generic list from a Firebase database in Unity3D without knowing ahead of time what the name (key) of the children are?
I have been trying out the new Unity Firebase plugin, and I am having an issue figuring out how to get all the children in a specific location, and put the names (the key) and the values into arrays or generic lists so that I can work on the data locally. Forgive me for being so new to Firebase and probably using bad techniques to do this, and this plugin being so new its pretty hard for me to get much outside help, as there are not a lot of docs and tutorials out there on Firebase Unity.
In this particular case I am trying to create "instant messaging" like functionality, without the use of Firebase messaging, and just using regular Firebase database stuff instead. It might have been easier to use Firebase messaging, but mostly for the sake of learning and customization I want to do this on my own with just the Firebase database.
I insert data into the database like this:
public void SendMessage(string toUser, string msg)
{
Debug.Log(String.Format("Attempting to send message from {0} to {1}", username, toUser));
DatabaseReference reference = FirebaseDatabase.DefaultInstance.GetReference("Msgs");
string date = Magnet.M.GetCurrentDate();
// send data to the DB
reference.Child(toUser).Child(username).Child(date).SetValueAsync(msg);
// user receiving message / user sending message > VALUE = "hello dude|20170119111325"
UpdateUsers();
}
And then I try and get it back like this:
public string[] GetConversation(string userA, string userB)
{
// get a conversation between two users
string[] convo = new string[0];
FirebaseDatabase.DefaultInstance.GetReference("Msgs").GetValueAsync().ContinueWith(task =>
{
Debug.Log("Getting Conversation...");
if (task.IsFaulted || task.IsCanceled)
{
Debug.LogError("ERROR: Task error in GetConversation(): " + task.Exception);
}
else if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
string[] messagesA = new string[0], messagesB = new string[0];
if(snapshot.HasChild(userA))
{
// userA has a record of a conversation with other users
if(snapshot.Child(userA).HasChild(userB)) // userB has sent messages to userA before
{
Debug.Log("Found childA");
long count = snapshot.Child(userA).Child(userB).ChildrenCount;
messagesA = new string[count];
var kids = snapshot.Child(userA).Child(userB).Children;
Debug.Log(kids);
for (int i = 0; i < count; i++)
{
// this won't work, but is how I would like to access the data
messagesA[i] = kids[i].Value.ToString(); // AGAIN.... will not work...
}
}
}
if(snapshot.HasChild(userB))
{
if(snapshot.Child(userB).HasChild(userA)) // userA sent a message to userB before
{
Debug.Log("Found childB");
long count = snapshot.Child(userB).Child(userA).ChildrenCount;
messagesA = new string[count];
var kids = snapshot.Child(userB).Child(userA).Children;
Debug.Log(kids);
// messy incomplete testing code...
}
}
// HERE I WOULD ASSIGN ALL THE MESSAGES BETWEEN A AND B AS 'convo'...
}
Debug.Log("Done Getting Conversation.");
});
return convo;
}
But obviously this won't work, because DataSnapshot won't let me access it like an array or generic list using indices, and I can't figure out how to treat the data when I don't know the names (the keys) of all the children, and just want to get them out one by one in any order... and since they are named by the date/time they are entered into the DB, I won't know ahead of time what the childrens names (keys) are, and I can't just say "GetChild("20170101010101")" because that number is generated when its sent to the DB from any client.
FYI here is what the DB looks like:
Figured out the answer to your question. Here's my code snippet. Hope this would help!
void InitializeFirebase() {
FirebaseApp app = FirebaseApp.DefaultInstance;
app.SetEditorDatabaseUrl ("https://slol.firebaseio.com/");
FirebaseDatabase.DefaultInstance
.GetReference ("Products").OrderByChild ("category").EqualTo("livingroom")
.ValueChanged += (object sender2, ValueChangedEventArgs e2) => {
if (e2.DatabaseError != null) {
Debug.LogError (e2.DatabaseError.Message);
}
if (e2.Snapshot != null && e2.Snapshot.ChildrenCount > 0) {
foreach (var childSnapshot in e2.Snapshot.Children) {
var name = childSnapshot.Child ("name").Value.ToString ();
text.text = name.ToString();
Debug.Log(name.ToString());
//text.text = childSnapshot.ToString();
}
}
};
}
Firebase developer here.
Have you tried to use Value at the top level Snapshot? It should return to you an IDictionary where the values can also be lists or nested dictionaries. You will have to use some dynamic inspection to figure out what the values are.

Spring LDAP AD paging support not working - LDAP: error code 12 - 00000057: LdapErr: DSID-0C09079A

When trying to run the code above I'm getting javax.naming.OperationNotSupportedException with the message:
[LDAP: error code 12 - 00000057: LdapErr: DSID-0C09079A, comment: Error processing control, data 0, v2580].
The first page is successfully retrieved and the exception is thrown only at second loop iteration.
public void pagedResults() {
PagedResultsCookie cookie = null;
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
int page = 1;
do {
logger.info("Starting Page: " + page);
PagedResultsDirContextProcessor processor = new PagedResultsDirContextProcessor(20, cookie);
List<String> lastNames = ldapTemplate.search("", initialFilter.encode(), searchControls, UserMapper.USER_MAPPER_VNT, processor);
for (String l : lastNames) {
logger.info(l);
}
cookie = processor.getCookie();
page = page + 1;
} while (null != cookie.getCookie());
}
However, when I remove Spring LDAP using pure implementation as above, it works!
try {
LdapContext ctx = new InitialLdapContext(env, null);
// Activate paged results
int pageSize = 5;
byte[] cookie = null;
ctx.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.CRITICAL) });
int total;
do {
/* perform the search */
NamingEnumeration results = ctx .search("",
"(&(objectCategory=person)(objectClass=user)(SAMAccountName=vnt*))",
searchCtls);
/* for each entry print out name + all attrs and values */
while (results != null && results.hasMore()) {
SearchResult entry = (SearchResult) results.next();
System.out.println(entry.getName());
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
total = prrc.getResultSize();
if (total != 0) {
System.out.println("***************** END-OF-PAGE "
+ "(total : " + total
+ ") *****************\n");
} else {
System.out.println("***************** END-OF-PAGE "
+ "(total: unknown) ***************\n");
}
cookie = prrc.getCookie();
}
}
} else {
System.out.println("No controls were sent from the server");
}
// Re-activate paged results
ctx.setRequestControls(new Control[] { new PagedResultsControl(
pageSize, cookie, Control.CRITICAL) });
} while (cookie != null);
ctx.close();
} catch (NamingException e) {
System.err.println("PagedSearch failed.");
e.printStackTrace();
} catch (IOException ie) {
System.err.println("PagedSearch failed.");
ie.printStackTrace();
}
Any hints?
The bad thing about LDAP paged results is that they only work if the same underlying connection is used for all requests. The internals of Spring LDAP get a new connection for each LdapTemplate operation, unless you use the transactional support.
The easiest way to make sure the same connection will be used for a sequence of LDapTemplate operations is to use the transaction support, i.e. configure transactions for Spring LDAP and wrap the target method with a Transactional annotation.
I managed to make my example above work using SingleContextSource.doWithSingleContext approach.
However my scenario is different, my app is service oriented and the paged results as well as the cookie should be sent to an external client so that he decides to request next pages or not.
So as far as I can tell, spring-ldap does not support such case. I must use pure implementation so that I can keep track of the underlying connection during requests. Transaction support could help as well as SingleContextSource, but not among different requests.
#marthursson
Is there any plan in spring ldap to such support in the future?
I found I could use your first example (Spring) as long as I set the ignorePartialResultException property to true in my ldapTemplate configuration and put the #Transactional on my method as suggested.
you can replace ldapTemplate DirContext like this
ldapTemplate.setContextSource(new SingleContextSource(ldapContextSource().getReadWriteContext()));

GKMatchRequest invitation not showing in other device

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!

Windows EXE can run as service or application. How can I determine if it is running as a service or not?

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

Resources