I would like to disconnect a bluetooth device from my c# .Net application, that runs on Win 7 x64.
I Know that MS provides very little functionnality reguarding BT on .Net.
I've searched 32feet.Net, and found how to connect, discover, get information, ... but nothing about disconnecting (Have I missed something ?).
Then, I found on Msdn IOCTL_BTH_DISCONNECT_DEVICE. The problem is that I can't understand how to call it.
It Seems that I shoud use DeviceIOControl with Platform Invoke, but I'm afraid that I haven't got enough .Net skills to build this by myself.
Here is where I am at the moment :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.IO;
namespace BtDisco
{
class Program
{
const int IOCTL_BTH_DISCONNECT_DEVICE = 0x41000c;
[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
public static extern bool DeviceIoControl(
Microsoft.Win32.SafeHandles.SafeFileHandle hDevice,
uint dwIoControlCode,
[MarshalAs(UnmanagedType.AsAny)] [In] object InBuffer,
uint nInBufferSize,
[MarshalAs(UnmanagedType.AsAny)] [Out] object OutBuffer,
uint nOutBufferSize,
ref uint pBytesReturned,
[In] ref System.Threading.NativeOverlapped Overlapped
);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern SafeFileHandle CreateFile(
string lpFileName,
[MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
[MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
IntPtr lpSecurityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
static void Main(string[] args)
{
//http://msdn.microsoft.com/en-us/library/windows/desktop/aa363216(v=vs.85).aspx
//hDev = Use CreateFile
SafeFileHandle _hdev = CreateFileR(...);
DeviceIoControl(hDev, IOCTL_BTH_DISCONNECT_DEVICE, char[] btAddr, btAddr.Length(), result, result.Length(), ref getCnt, IntPtr.Zero);
}
}
}
Could someone be kind enough to help me complete this ?
Finally, I have got it working by myself !
I searched a bit more in the InTheHand.Net code and finally understood how to make it !
Here is some working code (you will need InTheHand.Net if you want to use it):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Text;
using InTheHand.Net;
using InTheHand.Net.Bluetooth;
using System.Runtime.InteropServices;
namespace BTDisco2
{
class Program
{
const int IOCTL_BTH_DISCONNECT_DEVICE = 0x41000c;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
ref long InBuffer,
int nInBufferSize,
IntPtr OutBuffer,
int nOutBufferSize,
out int pBytesReturned,
IntPtr lpOverlapped);
static void Main(string[] args)
{
var r = BluetoothRadio.PrimaryRadio;
var h = r.Handle;
long btAddr = BluetoothAddress.Parse("00:1b:3d:0d:ac:31").ToInt64();
int bytesReturned = 0;
var success = DeviceIoControl(h,
IOCTL_BTH_DISCONNECT_DEVICE,
ref btAddr, 8,
IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);
if (!success)
{
int gle = Marshal.GetLastWin32Error();
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "failure: {0} = 0x{0:X}.", gle));
}
else
{
Console.WriteLine("Success !");
}
while (!Console.KeyAvailable) System.Threading.Thread.Sleep(200);
}
}
}
Related
So I recently stumbled onto a blog that described how to run your WinForms application from another process.
I instantly thought this was something really cool an unique and wanted to test it out myself. While there was no code it explained how to do so and this is what I've done.
class Program
{
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200)
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
Int32 nSize,
out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess,
IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress,
IntPtr lpParameter, uint dwCreationFlags, out IntPtr lpThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
ProcessAccessFlags processAccess,
bool bInheritHandle,
int processId
);
public static IntPtr OpenProcess(Process proc, ProcessAccessFlags flags)
{
return OpenProcess(flags, false, proc.Id);
}
static void Main(string[] args)
{
Process notepad = null;
Process[] processes = Process.GetProcesses();
foreach (var process in processes)
{
if (process.ProcessName.ToLower() == "notepad")
{
notepad = process;
}
}
OpenProcess(notepad, ProcessAccessFlags.All);
byte[] payload = File.ReadAllBytes(#"C:\Users\developer\source\repos\WindowsFormsApp2\WindowsFormsApp2\bin\Debug\WindowsFormsApp2.exe");
foreach (ProcessThread pt in notepad.Threads)
{
IntPtr openThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pt.Id);
SuspendThread(openThread);
CloseHandle(openThread);
}
WriteProcessMemory(notepad.Handle, notepad.Modules[0].BaseAddress, payload, payload.Length, out IntPtr lpNumberOfBytesWritten);
CreateRemoteThread(notepad.Handle, IntPtr.Zero, 0x0, notepad.Modules[0].BaseAddress, IntPtr.Zero, 0x0, out _);
}
}
It's something very simple that is supposed to suspend the process and all of it's threads.
And then write the bytearray from my other application which is a simple WinForms application witha button that when you click on it, it shows a MessageBox saying Hello World
But as soon as I run the code, notepad crashes and nothing shows up, where did I go wrong?
Check out this Memory problem with application in C# Windows Forms and also this High memory usage of a windows forms method. I'm led to believe you may have a caching issue or are not writing safe code for memory management. I would start by looking at your entry point to the program and debugging the foreach blocks.
I try to change the background using C#.Example:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32
uiParam, String pvParam, UInt32 fWinIni);
private static UInt32 SPI_SETDESKWALLPAPER = 20;
private static UInt32 SPIF_UPDATEINIFILE = 0x1;
And then
SystemParametersInfo(SPI_SETDESKWALLPAPER, 1, #"C:\background.bmp", SPIF_UPDATEINIFILE);
}
But it doesn't work...Help?
pvParam should be a local file. It will not work for urls...
First download the image, then give its local path to SystemParametersInfo method.
var filename = "4.jpg";
new WebClient().DownloadFile("http://www.scottgames.com/4.jpg", filename);
SystemParametersInfo(SPI_SETDESKWALLPAPER, 1, filename, SPIF_UPDATEINIFILE);
How do I find the new memory address in C# using my static address and offset.
base: 0x1023469C
offset: 1E8
I tried just adding the offset to the base inside of the readprocessmemory function but that didn't work at all :(
I am trying to read memory from this address as I am programming a little tool which will play a sound if my health in justcause 2 gets to low.
thanks for your help in advance :D
This is what I got so far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
//variabeln JC2
//Pointer
const int Offset = 0x1E8; // offset
const int Base = 0x1023469C; // base
const string Game = "The Game you don't know"; //Name
//permission to read process memory
const int PROCESS_WM_READ = 0x0010; //needed for reading memory
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[Out] byte[] lpBuffer,
int dwSize,
out int lpNumberOfBytesRead);
public Form1()
{
InitializeComponent();
}
private void BTcheck_Click(object sender, EventArgs e)
{
if (Process.GetProcessesByName(Game).Length > 0)
{
Process process = Process.GetProcessesByName(Game)[0];
IntPtr procHandle = OpenProcess(PROCESS_WM_READ, false, process.Id);
IntPtr baseAddress = new IntPtr(Base); //whatever address you wish
int offset = Offset; //whatever offset you wish
baseAddress += offset;
byte[] buffer = new byte[sizeof(int)]; //select a proper buffer size
int read = -1;
ReadProcessMemory(procHandle, baseAddress, buffer, buffer.Length, out read);
if (read == buffer.Length)
{
int value = BitConverter.ToInt32(buffer, 0);
//do something with it
LBcurrent.Text = Convert.ToString(value); //display the value
}
}
else
{ LBcurrent.Text = "Error!"; }
}
}
}
Here's how you do it (tested):
For the function import:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[Out] byte[] lpBuffer,
int dwSize,
out int lpNumberOfBytesRead);
For using it:
IntPtr procHandle = Process.GetCurrentProcess().Handle;
IntPtr baseAddress = new IntPtr(0x027EF131); //whatever address you wish
int offset = 0x100; //whatever offset you wish
baseAddress += offset;
byte[] buffer = new byte[sizeof(int)];
int read = -1;
ReadProcessMemory(procHandle, baseAddress, buffer, buffer.Length, out read);
if (read == buffer.Length)
{
int value = BitConverter.ToInt32(buffer, 0);
//do something with it
}
EDIT:
I've assumed you were trying to read from the current process memory, hence the procHandle = Process.GetCurrentProcess().Handle; part. Feel free to change that handle to whatever process handle you require and have permissions to.
EDIT:
I've edited the answer for reading 32-bit integet values. For 64 bit, use sizeof(long) for the buffer size and BitConverter.ToInt64.
UPD. I have the same situation in C++ win32 code.
C#:
WinAPI part:
const uint EVENT_CONSOLE_CARET = 0x4001;
const uint EVENT_CONSOLE_END_APPLICATION = 0x4007;
delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll", SetLastError = true))]
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax,
IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc,
uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
Code:
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.Start();
_winEventProc = new WinEventDelegate(WinEventProc);
m_hhook = SetWinEventHook(EVENT_CONSOLE_CARET,
EVENT_CONSOLE_END_APPLICATION,
IntPtr.Zero,
_winEventProc,
(uint) process.Id,
0,
WINEVENT_OUTOFCONTEXT);
lastError = Marshal.GetLastWin32Error();
My program cannot catch events from process that I've created. If I change "(uint) process.Id" to "(uint) 0" it working good. I changed "(uint) process.Id" to specific process Id (watched it in task manager) and result was the same(bad). I even tried:
1) start cmd.exe (*)
2) start my program without creating new cmd.exe process
3) press any key at cmd.exe(*)
4) use GetWindowThreadProcessId in _winEventProc
5) re-run my program with pID that I get on 4 step
And it doesn't work. I don't know why but it working well only with processID 0.
p.s. sorry for my bad english
For an example, I have a project (c#) which gives output from 1 to 5 numbers. And if that was one, I want the program to write 'A' in note pad. I didn't use FORM to create my project in c#. It's written in XML. So, May i know how could i do this.?
Like, i tried - SendKeys.Send("{A}"); when the event is fired. But as my project is not a form. I couldn't do it. Can anyone help me on this. :(
Thank You.
MY ACTUAL PROJECT:
I have done with emotion recognition. I have done with Second life emotions. I want to input the emotion detection in (C#) to second life. Only this is left. If I have had clarified my doubt, I could do it. Thank you.
In order to put "A" into the NotePad you can do
Find out NotePad Edit Window (assuming notepad.exe is executing)
Send WM_CHAR message to the window found
The code can be like that
Required Native API declarations:
internal delegate Boolean EnumerationCallback(IntPtr handle, IntPtr parameter);
[DllImport("User32.dll",
CallingConvention = CallingConvention.Winapi,
EntryPoint = "EnumWindows",
CharSet = CharSet.Unicode,
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean EnumWindows(EnumerationCallback lpEnumFunc,
IntPtr lParam);
[DllImport("User32.dll",
CallingConvention = CallingConvention.Winapi,
EntryPoint = "EnumChildWindows",
CharSet = CharSet.Unicode,
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean EnumChildWindows(IntPtr hwndParent,
EnumerationCallback lpEnumFunc,
IntPtr lParam);
[DllImport("user32.dll",
CallingConvention = CallingConvention.Winapi,
EntryPoint = "GetClassNameW",
CharSet = CharSet.Unicode,
SetLastError = true)]
internal extern static int GetClassName(IntPtr hWnd,
[MarshalAs(UnmanagedType.LPWStr)]
StringBuilder name,
int size);
[DllImport("User32.dll",
CallingConvention = CallingConvention.Winapi,
EntryPoint = "GetWindowThreadProcessId",
SetLastError = true)]
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd,
out IntPtr ProcessId);
[DllImport("User32.dll",
EntryPoint = "SendMessageW",
CallingConvention = CallingConvention.Winapi,
SetLastError = true,
CharSet = CharSet.Unicode)]
internal extern static IntPtr SendMessage(IntPtr handle,
int message,
IntPtr wParam,
IntPtr lParam);
const int WM_CHAR = 0x102;
The solution itself:
public void PrintA() {
IntPtr handleNotePad = IntPtr.Zero;
IntPtr handleNotePadEdit = IntPtr.Zero;
// First, find NotePad Main window
EnumWindows(
(IntPtr h, IntPtr p) => {
int processId;
GetWindowThreadProcessId(h, out processId);
if (Process.GetProcessById(processId).ProcessName != "notepad")
return true;
handleNotePad = h;
return false;
},
IntPtr.Zero);
// Second find NotePad EDIT window as a child of NotePad Main window
EnumChildWindows(handleNotePad,
(IntPtr h, IntPtr p) => {
StringBuilder s = new StringBuilder();
s.Length = 500;
GetClassName(h, s, s.Length);
if (s.ToString() != "Edit")
return true;
handleNotePadEdit = h;
return false;
},
IntPtr.Zero);
// Finally, send the message
SendMessage(handleNotePadEdit, WM_CHAR, (IntPtr) 'A', IntPtr.Zero);
}