Get Device Id used by an App - Windows 10 Mobile

Hi,
I'm trying to hack an old game (it isn't available in the store anymore) for fun and learning purposes. I'm running W10 but the app is targeted for WP7.
The game encrypts all the files it saves with AES, using the Device Unique Id as the key. It gets the DUID with the following code:
Code:
private string DeviceId
{
get
{
if (string.IsNullOrEmpty(this.id))
{
byte[] numArray = (byte[]) DeviceExtendedProperties.GetValue("DeviceUniqueId");
this.id = "";
foreach (byte num in numArray)
this.id += num.ToString("X2");
if (string.IsNullOrEmpty(this.id))
this.id = "0D0FC36982524EBB25E1CA471F32824286B90F47";
}
return this.id;
}
}
The thing is I don't know how to get that ID from outside the app, which might be unique for the device and publisher. I've searched in all the app files in AppData and seems like it doesn't record the ID anywhere.
I've tried for days and considered other approaches with no luck. Ideas? Suggestions? Any help? Thanks.

Related

[Q] Standard and Professional

Newbie here. Maybe someone can give me some direction. I am writing an app for both standard and professional. I have 2 projects in my solution. One is for standard the othe is for professional. I am not sure if this is the right way or not but what I want to do is when the app opens it checks to see what platform is running and then runs the correct project. Any help would be greatly appreciated.
It is possible to create a single project that is capable of running on both platforms but there is quite a bit of groundwork you will have to do first.
Firstly, the main differences.
Standard : No touch screen i.e. No Mouse events. All user input is via the keyboard, buttons, D-PAD and ENTER. No Open/Save dialogboxes, you have to present the files to the user yourself. Message dialogs appear full screen.
Professional : None of the above limitations.
The are a few pointers here:
http://msdn.microsoft.com/en-us/library/bb985500.aspx
The following code will detect the platform and set the variable 'SmartPhone' to 1 (true) if the version is 'Standard'
Code:
#define MAX_LOADSTRING 100
int SmartPhone;
TCHAR szReturn[MAX_LOADSTRING];
SystemParametersInfo(SPI_GETPLATFORMTYPE,MAX_LOADSTRING,szReturn,false);
SmartPhone=wcscmp(TEXT("SmartPhone"),szReturn)^1;
Your processing code may have code such as:
Code:
if(SmartPhone)
{
........ Standard Stuff.......
}
else
{
......... Professional Stuff........
}
Note also that code dealing with a WM_LBUTTONDOWN message will never be executed on a smartphone, as WinMo Standard never generates this message.
It may seem a pain, but you only have one executable to deliver for both platforms.
As an example, here's one I prepared earlier.
http://forum.xda-developers.com/showthread.php?t=509413
more info
I am coding with VB. What I was thinking was creating a class project and making that the startup project. Within the class the VB would check the platform and then run the correct project.
Should work:
To get the Platform type in .NET CF have a look at:
http://msdn.microsoft.com/en-us/library/ms229660(VS.90).aspx
It's also listed in the VS Help.
I am using VS2008 TS and cf3.5. I have tried several methods and still can't get any to work. I must be missing a reference or something. Here is some code I can't get to work.
If SystemSettings.Platform = WinCEPlatform.PocketPC Then
txtDeviceType.Text = "Windows Mobile Professional"
ElseIf SystemSettings.Platform = WinCEPlatform.Smartphone Then
txtDeviceType.Text = "Windows Mobile Standard"
Else
txtDeviceType.Text = "Not Windows Mobile"
End If
Also tried this.
Public Enumeration WinCEPlatform
Dim instance As WinCEPlatform
I also tried getversionex but couldn't get it to work either.
I only code .NET in C# but there is virtually no difference.
Try this: You will have to add the reference to Microsoft.WindowsCE.Forms;
Right click on References in the Solution Explorer, click on Add Reference, in the .NET Tab, pick it out of the list.
Code:
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.WindowsCE.Forms;
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
WinCEPlatform Platform = new WinCEPlatform();
Platform = SystemSettings.Platform;
label1.Text = Platform.ToString();
}
}
}
Works a treat!
Let's let Red Gate's Reflector translate the IL into VB.
It also reveals that the compiler rips outs the middle variables and goes straight for :
Code:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
Me.label1.Text = SystemSettings.Platform.ToString
End Sub
I am getting an error on this InitializeComponent. Another question. Can I add a class project and use this code to point to the correct project?
Drop the InitialiseComponent function, that is only used used in C#
In VB in Form1 the only code you need is
Code:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Label1.Text = Microsoft.WindowsCE.Forms.SystemSettings.Platform.ToString
End Sub
End Class
This code works and puts "YES" in the box if run on a PPC
Code:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Microsoft.WindowsCE.Forms.SystemSettings.Platform = Microsoft.WindowsCE.Forms.WinCEPlatform.PocketPC Then
Label1.Text = "YES"
End If
End Sub
End Class
Ok. I got it to work with the following code. But I have another problem. My app is a very simple app. I want it to work on PPC2003 and smartphones. I have 2 different forms for standard and professional. Now the problem is that if I use .net compact framework 3.5 then the device has to have that installed. So if I want to the app to work on older devices it won't work without the .net compact framework. If I use .net compact framework 2.0 then I lose the ability to use the code to determine if its standard or professional. I was hoping there was a way to include the 3.5 CF into my app cab but I haven't seen it. I am currently using VS2008 whcih only allows you 2.0 CF and 3.5 CF. I was thinking about using VS2005 and use 1.0 CF so it would work on all Windows mobile devices. But then I would again lose the ability to use the code. Any ideas would be appreciated.
Shared Sub Main()
Dim Platform As New WinCEPlatform()
Platform = SystemSettings.Platform
If Platform = "1" Then
Application.Run(
New Pro())
ElseIf Platform = "2" Then
Application.Run(
New Standard())
End If
End Sub
Using VS2005 I started a new project and selected SmartDevice 1.0. Now I have some issues.
1. Trying to determine either standard or professional. I am trying to use the Pinvoke to do this. No luck so far. I get an error on ByVal nFolder As ceFolders.
2. The code I was using to play a .wav file no longer works.
Dim myplayer As New System.Media.SoundPlayer(New IO.MemoryStream(My.Resources.Dice))
myplayer.Play()
3. I had resource files for images and a wav file so my code to use these no longer work.
Me.PictureBox1.Image = My.Resources.red_die_1_th
1. I'll have a look at it. Watch this space.
2. The SoundPlayer object is only available from .net CF 3.5 onwards. To play sounds you my have to PInvoke PlaySound()
http://msdn.microsoft.com/en-us/library/ms229685(v=VS.80).aspx
3. Should work, but maybe there's a difference in the frameworks. Microsoft's catch-all is that not all methods, properties etc. are supported in all .NET or .NET CF. versions. You may end up doing it in two stages, create a bitmap image from the resource, then pass that to the picturebox.
The answer to 1 is below. This works in C# under VS2003 .NET CF 1.0 but it is only in C#, I do not have VB installed on this machine. You will have to reverse engineer it into VB yourself, not too difficult. The important code is the DLLImport definition, the SPI_GETPLATFORMTYPE definition, and the call of the function in Form1_Load().
On program start "PocketPC" appears in the label on screen.
Code:
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
namespace PInvTest
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.MainMenu mainMenu1;
[DllImport("coredll.dll", EntryPoint="SystemParametersInfo", SetLastError=true)]
private static extern int SystemParametersInfo(
int uiAction, int uiParam, string pvParam, int fWinIni);
private const int SPI_GETPLATFORMTYPE = 257;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
string Platform = new string(' ',20);
SystemParametersInfo(SPI_GETPLATFORMTYPE,Platform.Length,Platform,0);
label1.Text=Platform;
}
}
}

[Q] How to delete/add an item from a ListBox?

Hi there,
I have a ListBox bounded to a query (linq to xml)
Dim CASDAs XDocument = XDocument.Load("./Data/CASD.xml")
Dim CAS_Query As System.Collections.IEnumerable = From query In Cartridge_Doc.Descendants("Cartridges") Order By _
CStr(query.Element("AA")) Descending, CStr(query.Element("AA"))
Select New Cartridge_Data With {.AA1 = CStr(query.Element("AA")), _
.BB1= CStr(query.Element("BB")), _
.CC1 = CStr(query.Element("CC"))}
Me.ListBox_1.ItemsSource = CAS_Query
Now, what I need to do is to select an item and have the option to delete it.
So far, I always got a run-time exception when trying this
Me.ListBox_1.Items.Remove(Me.ListBox_1.SelectedItem)
System.InvalidOperationException was unhandled
Message=Operation not supported on read-only collection.
So far I have tried a lot of options without any luck.
Any help will be greatly appreciated!
Thanks in advance.
Stick your Linq result in an ObservableCollection, bind this to the Listbox and delete the item directly from the underlaying collection.
emigrating said:
Stick your Linq result in an ObservableCollection, bind this to the Listbox and delete the item directly from the underlaying collection.
Click to expand...
Click to collapse
Please, can you poost a little code to do that? I'm fairly new to this collections world.
On the other hand, once the item got deleted, how the Listbox gets refreshed?
Thanks!
You have to set up an NotifyPropertyChanged class to keep the listbox updated with your collection. The default phone list application template that comes with Visual Studio shows you how to do this. I think its's in c# though and it looks like you're coding in VB. I'm sure there's examples in VB you can find on the web with a little searching.
Ren13B said:
You have to set up an NotifyPropertyChanged class to keep the listbox updated with your collection. The default phone list application template that comes with Visual Studio shows you how to do this. I think its's in c# though and it looks like you're coding in VB. I'm sure there's examples in VB you can find on the web with a little searching.
Click to expand...
Click to collapse
My ListBox takes its data from an XML file via query.
Which strategy do you think is the best?
To first delete the Xelement then refresh the ListBox?
Or deleting from the item from the ListBox, then update the XML file?
Sorry but I have all the samples from MS and didn't find any phone list one.
Any code will be greatly appreciated!
Oops. It's called "Windows Phone Databound Application". Attached is a screenshot of the project if it makes it easier for you to find it.
It's hard to post code because I don't know what your xaml looks like and bindings have to be set there for it to work. The best thing you can do is load the above project and play around with it.
You never have to refresh the items in the listbox. A bound listbox updates itself when an item in the collection changes. Change the collection and your listbox will reflect those changes. The NotifyPropertyChanged class is what triggers the listbox to update itself.
I do C#, not VB but the following should give you some idea.
Code:
public class Model : INotifyPropertyChanged
{
public string Title { get; set; }
public string Blurb { get; set; }
public event PropertyChangedEventHandler PropChanged;
public void NotifyPropertyChanged(String _propName)
{
if (null!=PropChanged)
{ PropChanged(this, new PropertyChangedEventArgs(_propName)); }
}
}
The above is your model, create any properties you need there - i.e. one per item of data in your XML file.
Next, you need to create an ObservableCollection somewhere, for the sake of simplicity let's stick it in your MainPage.xaml.cs file for now, so;
Code:
public partial class MainPage : PhoneApplicationPage
{
public ObservableCollection<Model> Items { get; set; }
public MainPage()
{
InitializeComponent();
this.Items = new ObservableCollection<Model>();
MyListBox.ItemsSource = this.Items;
WebClient wc = new WebClient();
wc.OpenReadCompleted += wc_OpenReadCompleted;
wc.OpenReadAsync(new Uri("http://your.server.here/datafile.xml");
}
public void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
using (Stream s = e.Result)
{
XDocument xd = Xdocument.Load(s);
var XMLdata = (from q in doc.Descendants("Item") select new Model()
{
Title = (string)q.Element("Title"),
Blurb = (string)q.Element("Blurb")
}
foreach (Model m in XMLdata)
{
this.Items.Add(m);
}
}
}
public MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lb = (ListBox)sender;
if (lb.SelectedIndex == -1)
return;
this.Items.Remove(lb.SelectedItem)
}
}
This will create a collection named Items as well as tell your ListBox (named MyListBox) to get it's data from said collection. Then it will read (asynchroniously) the XML file from the web and copy each item of data into your collection.
When you select an item in your ListBox it will be deleted from the ObservableCollection which in turn will remove it from the view (ListBox). At this stage you want to include code to also remove this from your actual XML file and so on of course. But the idea is that you work on your Collection only and your View will update based on what is changed - automagically.
Please note, the above code may or may not work out of the box. Written directly here on the forums so it hasn't gone thru VS2010's excellent IntelliSense. Also, the above code is in no way the most efficient way of doing certain things, but it gives you an idea as to what code you need to write to handle your scenario.
While I wrote this I see you've got an answer above which directs you to the VS template - use that and everything should become clear. All you have to remember is that perform operations on the Collection - not directly on the ListBox and you'll be fine.
Emigrating and Ren13B,
Thanks to both of you for the help. Very appreciated!
Will take both advices to see what comes up.
Thanks!

[Q] ListBox Binding Error with Observable Collection

Hi all!
Since days I have a problem now. I have an app that manage Entries in a list A. If one of these entries End-Date is today I whant that entry to be shown in a second list B. This is checked when I return from the "addNewItem" Window so I use onNavigatedTo.
Code:
// Static Variables
public static ObservableCollection<Item> lstToday = new ObservableCollection<Item>();
public static ObservableCollection<Item> lstWeek = new ObservableCollection<Item>();
public static ObservableCollection<Item> lstAll = new ObservableCollection<Item>();
// Constructor
public MainPage()
{
InitializeComponent();
MessageBox.Show("Initialize Component");
lbToday.ItemsSource = lstToday;
lbWeek.ItemsSource = lstWeek;
lbAll.ItemsSource = lstAll;
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
DateTime currentDate = DateTime.Now;
foreach (Item item in lstAll)
{
if (item.endDate.ToString("yyyy'-'MM'-'dd").Equals(currentDate.ToString("yyyy'-'MM'-'dd")))
{
lstToday.Add(item);
MessageBox.Show("Item '" + item.name + "' added to Todaylist");
}
}
}
private void appBarNew_Click(object sender, EventArgs e)
{
NavigationService.Navigate(new Uri(string.Format("/EditAddItem.xaml"), UriKind.Relative));
}
After that I get an "System.Diagnostics.Debugger.Break();" error that doesn't occur when I delete "lbToday.ItemsSource = lstToday;" to avoid the ListBox Binding.
With lbAll ist runs without any problems!
Can I bind the Listbox direct to the ObservableCollection in XAML=
I really don't know, whats to do. So do you?
It would make my day!
Thanks!
What is the exception message and stack trace when the exception is thrown? (you can browse the properties of the exception using visual studio).
Your code actually works for me (although I had to make some assumptions about what is in lstAll as you don't mention that, and you may have an error in the DataTemplate for the listbox for binding your Item class)
Things to try:
Have you tried it with non static observable collections?
Use binding assignments in the xaml rather than setting the itemssource directly (e.g. using a viewmodel). Then you can let the phone engine worry about when to do the assigments. If you do that don't forget to set the page's datacontext property.
Try it with simple collections of strings first (rather than binding an 'item' class) so you can check it's working without a datatemplate.
Hope you fix it.
Ian

Successful TCP Connection via CoreCon

So during my break today I added a few more registry paths to check on my HTC Radar and I found HKCU\Software\Microsoft\ConMan\HostLauncher\HostData\. There I found a few Service entries:
Code:
7ABBE0D5-B437-42CA-B57B-CEED61680E4F
11EE50CA-6CD3-45BA-9D65-46E133CFF009
B2FC26AB-D6EC-4426-91FA-9E039F92A639
The first entry did not take me any where but the other two did.
Running those in my test application sent back:
Code:
Int32Type: 0
Int32Type: -2147024809
I know it isnt much and I am not sure what to send to the ConMan so if someone does please tell me:
Code:
private static void ExecutionTest()
{
#region Create Objects
ObjectId DeviceID = new ObjectId("30F105C9-681E-420b-A277-7C086EAD8A4E");
Platform platform = datastoremanager.GetPlatform(PlatformObjectID);
Device device = platform.GetDevice(DeviceID);
#endregion
try
{
//Connect to the device.
device.Connect();
if (device.IsConnected())
{
RemoteAgent ra = device.GetRemoteAgent(new ObjectId("910DCB1B-487B-452b-87FC-73852B5A239C"));
DevicePacketStream ps = ra.CreatePacketStream(new ObjectId(new Guid("11EE50CA-6CD3-45BA-9D65-46E133CFF009")));
// Create and write a packet of data.
Packet packet;
packet = new Packet();
for (int i = 0; i < 4; i++) packet.WriteInt32(i);
packet.WriteString("Hello Smart Device");
ps.Write(packet);
#region While stream is connected, try to read a packet.
while (ps.IsConnected())
{
if (ps.IsPacketAvailable())
{
packet = ps.Read();
while (!packet.IsEndOfPacket())
{
switch (packet.ReadDataType())
{
case DataType.BoolType: bool boolValue = packet.ReadBool(); break;
case DataType.ByteArrayType: byte[] buffer = packet.ReadBytes(); break;
case DataType.ByteType: byte byteValue = packet.ReadByte(); break;
case DataType.CharType: char charValue = packet.ReadChar(); break;
case DataType.Int32Type: Console.WriteLine("Int32Type: " + packet.ReadInt32().ToString()); break;
case DataType.StringType: Console.WriteLine("String: " + packet.ReadString()); break;
default: break;
}
}
break;
}
System.Threading.Thread.Sleep(1000);
}
#endregion
}
}
catch (Exception ex)
{
throw ex;
}
finally { device.Disconnect(); }
}
Huh, you got the remote "GetRemoteAgent" working. Right?
I think i might know how to resolve what to call in to the packet. VS2010 talks to wp7, and uses one of those GUID's; meaning one should be able do binary search all files (in a rom) to see who owns the GUID (what dll handler), disassemble that dll (to ASM/c), and extract "what it wants".
Or if MS has a hidden caller class somewhere
Ill look further into this, thanks
fiinix said:
Huh, you got the remote "GetRemoteAgent" working. Right?
I think i might know how to resolve what to call in to the packet. VS2010 talks to wp7, and uses one of those GUID's; meaning one should be able do binary search all files (in a rom) to see who owns the GUID (what dll handler), disassemble that dll (to ASM/c), and extract "what it wants".
Or if MS has a hidden caller class somewhere
Ill look further into this, thanks
Click to expand...
Click to collapse
Yes I did . Yeah I just need to know what to actually send to to the device. I know Visual Studio communicates this way.
MJCS said:
Yes I did . Yeah I just need to know what to actually send to to the device. I know Visual Studio communicates this way.
Click to expand...
Click to collapse
Great
I, myself tried 20+ GUID's once (from wp7 that _could_ be); all threw exceptions (aka not a remote agent handler).
It feels better now knowing what GUID's i can use.
Well the reg path was quite obvious; why did i not stumble upon that one earlier..
fiinix said:
Great
I, myself tried 20+ GUID's once (from wp7 that _could_ be); all threw exceptions (aka not a remote agent handler).
It feels better now knowing what GUID's i can use.
Well the reg path was quite obvious; why did i not stumble upon that one earlier..
Click to expand...
Click to collapse
Well I only found it since I know have an HTC Radar. My Dell venue pro requires you to manually enter in registry paths to see if they exist or not. I was able to decompile an older HTC registry viewer and then fix it so it didnt require interop unlock.
It should be possible to do registry browsing (but not editing) just fine on a DVP using the standard tools, unless there's a check that specifically blocks them. The browsing uses a native homebrew DLL that doesn't require ID_CAP_INTEROPSERVICES and has no device-specific dependencies. It's the editing that requires interop-unlock and device-specific DLLs.
GoodDayToDie said:
It should be possible to do registry browsing (but not editing) just fine on a DVP using the standard tools, unless there's a check that specifically blocks them. The browsing uses a native homebrew DLL that doesn't require ID_CAP_INTEROPSERVICES and has no device-specific dependencies. It's the editing that requires interop-unlock and device-specific DLLs.
Click to expand...
Click to collapse
There is no GetSubKeys method...anyways lets get back on topic.
I've been trying for weeks to get anything out of this. Nothing so far. I did find out that the Developer unlock is just a byte array of a cookie taken from Microsoft's auth server.
Has anyone had any success with this socket method yet? I really don't know enough about sockets to try.
BTW you have to have a core con connection to the device already open either from app debugging or some other method

Advice on strategy

I'm developing a WP7 app, working alongside a Windows (server) application. They are talking with each other using sockets.
As soon as the WP7 app opens, I wish to perform a network scan to find the server application.
I already found out how to get the IP address of the WP7. So let's say I know the server should be somewhere at 192.168.0.*. How do I go about scanning this network?
I tried many things, the last of which is the code below. The problem here is that somehow the TIMEOUT_MILLISECONDS parameter seems to be like playing roulette (tried everything in the range of 100-2000 with different success). In addition, if I sweep the whole subnet like in the code below the phone cannot seem to handle the work. I only get it to work if I set the timeout to 2000 (which is way to long) and by scanning up to 5 IP's in the for-loop, instead of the whole subnet.
Is there anyone that knows a better and much more efficient(!) way to do this?
Code:
string thisIP = "192.168.0.101"; // I normally get this from some other function
string[] arrIP = thisIP.ToString().Split('.');
string IPBase = arrIP[0] + "." + arrIP[1] + "." + arrIP[2] + ".";
//MessageBox.Show(address.ToString());
for (int i = 2; i < 254; i++) {
string IP = IPBase + i;
CheckConnection CheckConn = new CheckConnection();
string resultConnect = CheckConn.Connect(IP, int.Parse(Resource1.port));
if (resultConnect == "Success") {
CheckConn.Send("isAlive");
string result = CheckConn.Receive();
if (result.Contains("yes")) {
// We have found the server
break;
}
}
CheckConn.Close();
}
Code:
public class CheckConnection
{
// Cached Socket object that will be used by each call for the lifetime of this class
Socket _socket = null;
static ManualResetEvent _clientDone = new ManualResetEvent(false);
const int TIMEOUT_MILLISECONDS = 100;
const int MAX_BUFFER_SIZE = 2048;
public string Connect(string hostName, int portNumber) {
string result = string.Empty;
DnsEndPoint hostEntry = new DnsEndPoint(hostName, portNumber);
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = hostEntry;
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) {
result = e.SocketError.ToString();
_clientDone.Set();
});
_clientDone.Reset();
_socket.ConnectAsync(socketEventArg);
_clientDone.WaitOne(TIMEOUT_MILLISECONDS);
return result;
}
public string Send(string data) {
string response = "Operation Timeout";
if (_socket != null) {
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;
socketEventArg.UserToken = null;
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) {
response = e.SocketError.ToString();
_clientDone.Set();
});
byte[] payload = Encoding.UTF8.GetBytes(data);
socketEventArg.SetBuffer(payload, 0, payload.Length);
_clientDone.Reset();
_socket.SendAsync(socketEventArg);
// Block the UI thread for a maximum of TIMEOUT_MILLISECONDS seconds.
// If no response comes back within this time then proceed
_clientDone.WaitOne(TIMEOUT_MILLISECONDS);
}
else {
response = "Socket is not initialized";
}
return response;
}
public string Receive() {
string response = "Operation Timeout";
if (_socket != null) {
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;
socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE);
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) {
if (e.SocketError == SocketError.Success) {
response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
response = response.Trim('\0');
}
else {
response = e.SocketError.ToString();
}
_clientDone.Set();
});
_clientDone.Reset();
_socket.ReceiveAsync(socketEventArg);
_clientDone.WaitOne(TIMEOUT_MILLISECONDS);
}
else {
response = "Socket is not initialized";
}
return response;
}
public void Close() {
if (_socket != null) {
_socket.Close();
}
}
}
Why you don't know the server IP?
I can't help you with your subnet scanning problem, don't have experience with that corner of WP7 programming.
But I do wonder what kind of arrangement leads to the problem that your app does not know the server address and therefore has to scan for it. Is neither a fixed IP available for your server nor some kind of DNS service up to tell you the current IP?
Even if there are multiple servers running and the phone has the job to somehow decide which one of those is responsible for it, you still could set up some kind of super-server that the phones could ask first which server they should address.
In any way, phones scanning subnets to find servers as some routine app startup action is a bad idea, if you ask me.
Please note that by 'server' I'm just revering to a software that accepts socket connections. This software is installed into a Windows computer that most likely has it's IP from DHCP.
The server software itself could present it's IP address so the end-user can type this address into the client on their WP7. Nice for tech-savvy folks, but that's not how software should be designed in my opinion. People don't need to know what an IP address is and shouldn't be force into typing 'weird numbers'. Properly designed software just have to work instantly and developers (again in my opinion) need to take care of a good design and that includes making things plug-and-play where they can.
Take a look at 'PC Remote' and you will see the kind of easy plug-and-play experience I'm looking for.
Did you check broadcast?
I'm really not network guy, but from Googling I got the impression that people use broadcast instead of IP range scanning for such IP number discovery tasks, and there seems to be a way to do broadcast on WP7 (albeit only using some tricks / hardly documented functionalilty):
E.g. see this thread:
http://stackoverflow.com/questions/8533471/udp-broadcasting-in-windows-phone-7
Which links to this:
http://forums.create.msdn.com/forums/t/88975.aspx
This makes sense to me after reading that broadcast is also the method how a client finds its DHCP server - isn't that the exact same scenario like yours?
Did you already check this way of looking at the problem, or maybe rule it out already for some reason?
It's better if you use a multicast group to send/receive packages. I had way better experience with it than using the Broadcast IP.
You need to join the multicast group with the phone and with the server app. I know there are multicast classes but I found it easier and mor convient to implement it with a socket...
And after you found the server, I'd use a persistent tcp connection which should improve your network performance (udp and wp7 is sometimes really strange...)
Thanks rbrunner7 and chabun for your comments, I appreciate your input!
rbrunner7 said:
Did you already check this way of looking at the problem, or maybe rule it out already for some reason?
Click to expand...
Click to collapse
I did, briefly, but abandoned this path after reading about the physical network equipment (switches etc.) having the need to support broadcasting which might not always be the case.
Anyway, your mentioned post describes 'limited broadcasting', which might be exactly what I should be looking for. Hopefully hardware limitations will not be applicable; I will look into this method further and will let you know how it works out!
roady001 said:
the physical network equipment (switches etc.) having the need to support broadcasting which might not always be the case.
Click to expand...
Click to collapse
I had the same doubts about that as it's also the case for multicasting. Most modern equipement supports it though and you can always provide the possibility to manually enter the server ip if you can't discover one via multicast/broadcast

Categories

Resources