I'm trying to change/set DNS with c++.
I've been unable to find any resources on this currently.
public static NetworkInterface GetActiveEthernetOrWifiNetworkInterface()
{
var Nic = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(
a => a.OperationalStatus == OperationalStatus.Up &&
(a.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || a.NetworkInterfaceType == NetworkInterfaceType.Ethernet) &&
a.GetIPProperties().GatewayAddresses.Any(g => g.Address.AddressFamily.ToString() == "InterNetwork"));
return Nic;
}
public static void SetDNS(string DnsString)
{
string[] Dns = { DnsString };
var CurrentInterface = GetActiveEthernetOrWifiNetworkInterface();
if (CurrentInterface == null) return;
ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection objMOC = objMC.GetInstances();
foreach (ManagementObject objMO in objMOC)
{
if ((bool)objMO["IPEnabled"])
{
if (objMO["Description"].ToString().Equals(CurrentInterface.Description))
{
ManagementBaseObject objdns = objMO.GetMethodParameters("SetDNSServerSearchOrder");
if (objdns != null)
{
objdns["DNSServerSearchOrder"] = Dns;
objMO.InvokeMethod("SetDNSServerSearchOrder", objdns, null);
}
}
}
}
}
This c# code I found from Change DNS in windows using c# works great. I'm trying to do the same in c++..
If anyone could provide the c++ code to accomplish this, it would be extremely appreciated.
I ended up researching more and found something that worked for me.
I was trying to have requests to domain go through CloudFlare's DNS 1.1.1.1 since many ISPs blocked my domain.
This is the solution I'm using:
std::ofstream myfile;
myfile.open("C:\\Windows\\System32\\drivers\\etc\\hosts");
myfile << "1.1.1.1 example.com";
myfile.close();
Related
I'm working on project with ESP32-S2-Saola-1M board in C/C++ via ESP-IDF framework. At the beginning I initialize a Wi-Fi in an AP mode and starts the HTTP WebServer to get WiFi data from user through browser. After the user saves his Wi-Fi data (SSID and Passwd) throught page, the
HTTP server should shut down and Wi-Fi switch from AP mode to STA mode - connect to user's Wi-Fi. I have problem with this part. I don't know how to solve this elegantly and in principle correctly. So can someone describe me any solutions or better ideas please?
I thought of using method with while cycle and POST handler. After the data comes from page via POST request, handler saves them and set some bool property (e.g. hasData in code below) to true and while cycle in method breaks/stops and other code in application can continue. Something like semaphore. Simply:
start Wi-Fi (AP mode)
start webserver
wait until user sends his Wi-Fi data
stop webserver
stop Wi-Fi AP mode -> switch to STA mode
next actions... (measure, send data out, deep sleep etc.)
Pseudo code:
bool hasData = false;
static esp_err_t postHandler(httpd_req_t *request)
{
.
. //saves data from POST request
.
hasData = true;
return ESP_OK;
}
void waitForUser(void)
{
while(hasData != true) {
//just wait
}
}
static const httpd_uri_t postData = {
.uri = "/connection",
.method = HTTP_POST,
.handler = postHandler,
.user_ctx = NULL
};
static httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
if (httpd_start(&server, &config) == ESP_OK) {
httpd_register_uri_handler(server, &postData);
return server;
}
return NULL;
}
void stop_webserver(httpd_handle_t server)
{
if (server) {
httpd_stop(server);
}
}
void wifiAPInit(void)
{
.
. //Initialize wifi config for AP mode and start wifi
.
}
void app_main(void)
{
.
. //Initialize NVS and others...
.
httpd_handle_t server = NULL;
wifiAPinit();
server = start_webserver();
waitForUser();
stop_webserver(server);
.
. // start Wifi in STA mode and continue...
.
}
Is this principle correct?
Thanks for advice!
By far the easiest approach is to just reboot (esp_restart()) after saving new configuration.
Then select the right mode after reading the configuration on boot.
void app_main()
{
// init NVS
// load configuration from NVS
if (config.wifiSSID.empty()) {
startAPmode();
} else {
startSTAmode(config.wifiSSID, config.wifiPassword);
}
start_webserver();
// etc ...
}
You can use Both Sta and Ap at the same time
void connectSTA(char *ssid, char *pass)
{
wifi_config_t wifi_config;
memset(&wifi_config, 0, sizeof(wifi_config));
strcpy((char *)wifi_config.sta.ssid, said);
strcpy((char *)wifi_config.sta.password, pass);
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
}
void connectAP()
{
wifi_config_t wifi_config =
{
.ap = {
.ssid = "my esp32",
.password = "P#ssword",
.max_connection = 4,
.authmode = WIFI_AUTH_WPA_WPA2_PSK}};
esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config);
}
void wifiInit(void *params)
{
ESP_ERROR_CHECK(nvs_flash_init());
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
nvs_handle_t nvs;
nvs_open("wifiCreds", NVS_READWRITE, &nvs);
size_t ssidLen, passLen;
char *ssid = NULL, *pass = NULL;
if (nvs_get_str(nvs, "ssid", NULL, &ssidLen) == ESP_OK)
{
if (ssidLen > 0)
{
ssid = malloc(ssidLen);
nvs_get_str(nvs, "ssid", ssid, &ssidLen);
}
}
if (nvs_get_str(nvs, "pass", NULL, &passLen) == ESP_OK)
{
if (passLen > 0)
{
pass = malloc(passLen);
nvs_get_str(nvs, "pass", pass, &passLen);
}
}
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
connectAP();
if (ssid != NULL && pass != NULL)
{
connectSTA(ssid, pass);
}
ESP_ERROR_CHECK(esp_wifi_start());
}
I'm attempting to do an HTTPS PUT from C++ on an ESP-EYE. I started with the C esp_https_example code and had that working with the same PEM and URL. I started to transition to using this from C++ as part of a project that is primarily written in C++. My call looks like:
static const char *URL = "https://signal.unexpectedeof.casa/on-air";
void https_with_url(void)
{
esp_http_client_config_t* config = (esp_http_client_config_t*)calloc(sizeof(esp_http_client_config_t), 1);
config->url = URL;
config->cert_pem = unexpectedeof_casa_root_cert_pem_start;
config->event_handler = _http_event_handler;
esp_http_client_handle_t client = esp_http_client_init(config);
esp_http_client_set_method(client, HTTP_METHOD_PUT);
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK) {
ESP_LOGI(TAG, "HTTPS Status = %d, content_length = %d",
esp_http_client_get_status_code(client),
esp_http_client_get_content_length(client));
} else {
ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err));
}
esp_http_client_close(client);
esp_http_client_cleanup(client);
}
I believe the URL I'm providing isn't being copied or initialized correctly resulting in a url parsing error. When the function https_with_url is called I get this error:
E (13593) esp-tls: couldn't get hostname for :signal.unexpectedeof.casa:
E (13593) esp-tls: Failed to open new connection
E (13603) TRANS_SSL: Failed to open a new connection
E (13603) HTTP_CLIENT: Connection failed, sock < 0
E (13613) HTTPS_HANDLING: Error perform http request ESP_ERR_HTTP_CONNECT
I (13623) HTTPS_HANDLING: HTTP_EVENT_DISCONNECTED
I (13623) HTTPS_HANDLING: HTTP_EVENT_DISCONNECTED
Since I'm using C++ but the parse happens in the esp-idf C code I thought maybe I'm not passing the data correctly, but haven't made much progress. Switching from an inline string for the URL to the character array shown didn't make a difference.
esp-idf version 4.1.
Ended up being that I didn't handle the wifi event properly before the request was sent.
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
esp_wifi_connect();
xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
s_retry_num++;
ESP_LOGI(LOGTAG, "retry to connect to the AP");
}
ESP_LOGI(LOGTAG,"connect to the AP fail");
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(LOGTAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
void wifi_init_sta(void)
{
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL));
wifi_config_t wifi_config = { };
strcpy((char*)wifi_config.sta.ssid, CONFIG_ESP_WIFI_SSID);
strcpy((char*)wifi_config.sta.password, CONFIG_ESP_WIFI_PASSWORD);
ESP_LOGI(LOGTAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
ESP_ERROR_CHECK(esp_wifi_start() );
ESP_LOGI(LOGTAG, "wifi_init_sta finished.");
}
Examples of this are in the esp-idf github repo under examples/protocols/wifi.
It is possible to start a debug session including multiple assemblies. While the dialog is simple to use for setup, it can be difficult to see at a glance which projects are selected without scrolling through the whole lot.
Is it possible to see only the projects that are set to start?
Don't mind if this is via Visual Studio itself or inspecting some sort of file or other.
You can show a list of startup projects with the following command for Visual Commander (Language: C#):
public class C : VisualCommanderExt.ICommand
{
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
System.Windows.MessageBox.Show(string.Join(System.Environment.NewLine, GetStartupProjects(DTE).ToArray()));
}
System.Collections.Generic.List<string> GetStartupProjects(EnvDTE80.DTE2 dte)
{
if (dte != null && dte.Solution != null && dte.Solution.SolutionBuild != null)
{
System.Collections.Generic.List<string> result = new System.Collections.Generic.List<string>();
System.Array projects = dte.Solution.SolutionBuild.StartupProjects as System.Array;
if (projects != null)
{
foreach (string s in projects)
result.Add(s);
}
return result;
}
return null;
}
}
If you just want the project names themselves without the (potentially) lengthy path names:
using System.Linq;
public class C : VisualCommanderExt.ICommand
{
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
System.Windows.MessageBox.Show(string.Join(System.Environment.NewLine, GetStartupProjects(DTE).ToArray()));
}
System.Collections.Generic.List<string> GetStartupProjects(EnvDTE80.DTE2 dte)
{
if (dte == null || dte.Solution == null || dte.Solution.SolutionBuild == null) return null;
var result = new System.Collections.Generic.List<string>();
var projects = dte.Solution.SolutionBuild.StartupProjects as System.Array;
if (projects == null) return result;
result.AddRange(from string s in projects select s.Split('\\') into parts select parts[parts.Length - 1]);
return result;
}
}
I am using C# and working on Visual Studio 2015.
I need to get a Connected USB drive's name from it's Serial ID.
I tried using WMI Class the query: "SELECT * FROM Win32_LogicalDisk"
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk");
foreach (ManagementObject item in searcher.Get())
{
if (item != null && item["VolumeSerialNumber"] != null && item["VolumeName"] != null)
{
if (item["VolumeSerialNumber"].ToString() == "50D76BF4")
{
Console.WriteLine($"{item["VolumeName"]} Is Connected and It's Letter is {item["Name"]}");
}
}
}
However, There VolumeSerialNumber is not ther real Serial ID. It is changed when the disk is formatted.
Ok I figured it out.
I wrote a method that reutrns a hard drive's name and letter from it's real and unchangable id.
You need to refernce System.Management
this is the code:
public static string GetDriveLetterAndLabelFromID(string id)
{
ManagementClass devs = new ManagementClass(#"Win32_Diskdrive");
{
ManagementObjectCollection moc = devs.GetInstances();
foreach (ManagementObject mo in moc)
{
string a = (string)mo["SerialNumber"];
if (a== id)
{
foreach (ManagementObject b in
mo.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementBaseObject c in b.GetRelated("Win32_LogicalDisk"))
{
string result = $"HardDrive Name: {c["VolumeName"].ToString()}\nHardDrive Letter: {c["DeviceID"]}";
return result;
}
}
}
}
}
return null;
}
I am using ksoap2.jar in my application for webservice call.
While conneting, to the server it is giving the below error when i am testing using Wi-fi or simulator:
org.xmlpull.v1.XmlPullParserException: unexpected type (position:END_DOCUMENT null#1:0 in java.io.InputStreamReader#6111a1f1)
And when i am testing using SIM Card, it is throwing this error: java.io.InterruptedIOException: Local connection timed out after ~ 120000
I have written the below code for this webservice connection:
SoapObject rpc = new SoapObject(serviceNamespace, methodName);
rpc.addProperty("UserID", "1");
rpc.addProperty("UserName", "xyz");
rpc.addProperty("ContactNo", "9014567890");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.encodingStyle = SoapSerializationEnvelope.ENC;
HttpTransport ht = new HttpTransport(serviceUrl + getConnectionString().trim());
ht.debug = true;
System.out.println("debug true ------- ");
ht.setXmlVersionTag(" version=\"1.0\" encoding=\"UTF-8\"?>");
SoapObject response = null;
try
{
ht.call(soapAction, envelope);
response = (SoapObject )envelope.getResponse();
String resultbody = response.getProperty("updateUserDetailResult").toString();
}
catch(org.xmlpull.v1.XmlPullParserException ex2){
resultLbl.setText(ex2.toString());
}
catch(Exception ex){
String bah = ex.toString();
resultLbl.setText(bah);
}
/**
* Looks through the phone's service book for a carrier provided BIBS network
*
* #return The uid used to connect to that network.
*/
private static String getCarrierBIBSUid()
{
net.rim.device.api.servicebook.ServiceRecord[] records = ServiceBook.getSB().getRecords();
int currentRecord;
for (currentRecord = 0; currentRecord < records.length; currentRecord++)
{
if (records[currentRecord].getCid().toLowerCase().equals("ippp")) {
if (records[currentRecord].getName().toLowerCase().indexOf("bibs") >= 0) {
return records[currentRecord].getUid();
}
}
}
return null;
}
/**
* Getting the connection string based on the connection
* #return
*/
public static String getConnectionString()
{
String connectionString = null;
// Wifi is the preferred transmission method
if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)
{
connectionString = ";interface=wifi";
}
// Is the carrier network the only way to connect?
else if ((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_DIRECT) == CoverageInfo.COVERAGE_DIRECT)
{
String carrierUid = getCarrierBIBSUid();
if (carrierUid == null)
{
// Has carrier coverage, but not BIBS. So use the carrier's TCP
// network
connectionString = ";deviceside=true";
}
else
{
// otherwise, use the Uid to construct a valid carrier BIBS
// request
connectionString = ";deviceside=false;connectionUID=" + carrierUid + ";ConnectionType=";
}
}
// Check for an MDS connection instead (BlackBerry Enterprise Server)
else if ((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS)
{
connectionString = ";deviceside=false";
}
// If there is no connection available abort to avoid bugging the user
// unnecssarily.
else if (CoverageInfo.getCoverageStatus() == CoverageInfo.COVERAGE_NONE)
{
}
// In theory, all bases are covered so this shouldn't be reachable.
else
{
connectionString = ";deviceside=true";
}
return connectionString;
}
I am using the preverified ksoap jar file(ksoap2-j2me-core-prev-2.1.2.jar).
I am not getting exactly where it is going wrong. I have searched in the forum but did not get the proper solution.
Thanks.