diff --git a/dbus.cabal b/dbus.cabal
--- a/dbus.cabal
+++ b/dbus.cabal
@@ -1,5 +1,5 @@
 name: dbus
-version: 1.2.27
+version: 1.2.28
 license: Apache-2.0
 license-file: license.txt
 author: John Millikin <john@john-millikin.com>
diff --git a/lib/DBus/Client.hs b/lib/DBus/Client.hs
--- a/lib/DBus/Client.hs
+++ b/lib/DBus/Client.hs
@@ -156,6 +156,7 @@
     , clientThreadRunner
     , defaultClientOptions
     , connectWith
+    , connectWithName
 
     , dbusName
     , dbusPath
@@ -427,6 +428,36 @@
 -- Throws a 'ClientError' on failure.
 connectWith :: TransportOpen t => ClientOptions t -> Address -> IO Client
 connectWith opts addr = do
+    client <- connectWith' opts addr
+
+    callNoReply client (methodCall dbusPath dbusInterface "Hello")
+        { methodCallDestination = Just dbusName
+        }
+
+    return client
+
+-- | Connect to the bus at the specified address, with the given connection
+-- options, and return the unique client bus name. Most users should use
+-- 'connect' or 'connectWith' instead.
+--
+-- Throws a 'ClientError' on failure.
+connectWithName :: TransportOpen t => ClientOptions t -> Address -> IO (Client, BusName)
+connectWithName opts addr = do
+    client <- connectWith' opts addr
+
+    reply <- call_ client (methodCall dbusPath dbusInterface "Hello")
+        { methodCallDestination = Just dbusName
+        }
+    
+    case methodReturnBody reply of
+      [name] | Just nameStr <- fromVariant name -> do
+        busName <- parseBusName nameStr
+        return (client, busName)
+      _ ->
+        throwIO (clientError "connectWithName: Hello response did not contain client name.")
+
+connectWith' :: TransportOpen t => ClientOptions t -> Address -> IO Client
+connectWith' opts addr = do
     sock <- DBus.Socket.openWith (clientSocketOptions opts) addr
 
     pendingCalls <- newIORef M.empty
@@ -449,10 +480,6 @@
             , clientInterfaces = clientBuildInterfaces opts client
             }
     putMVar clientMVar client
-
-    callNoReply client (methodCall dbusPath dbusInterface "Hello")
-        { methodCallDestination = Just dbusName
-        }
 
     return client
 
diff --git a/tests/DBusTests/Client.hs b/tests/DBusTests/Client.hs
--- a/tests/DBusTests/Client.hs
+++ b/tests/DBusTests/Client.hs
@@ -69,6 +69,22 @@
     client <- readMVar clientVar
     DBus.Client.disconnect client
 
+test_ConnectWithName :: TestTree
+test_ConnectWithName = testCase "connectWithName" $ do
+    (addr, sockVar) <- startDummyBus
+    clientVar <- forkVar (DBus.Client.connectWithName DBus.Client.defaultClientOptions addr)
+
+    sock <- readMVar sockVar
+    receivedHello <- DBus.Socket.receive sock
+    let (ReceivedMethodCall helloSerial _) = receivedHello
+
+    let helloReturn = (methodReturn helloSerial) { methodReturnBody = [toVariant ":1.123"] }
+    DBus.Socket.send sock helloReturn (\_ -> return ())
+
+    (client, clientName) <- readMVar clientVar
+    assertEqual "client name not as expected" (busName_ ":1.123") clientName
+    DBus.Client.disconnect client
+
 suite_Connect :: TestTree
 suite_Connect = testGroup "connect"
     [ test_ConnectSystem
@@ -77,6 +93,7 @@
     , test_ConnectSession_NoAddress
     , test_ConnectStarter
     , test_ConnectStarter_NoAddress
+    , test_ConnectWithName
     ]
 
 test_ConnectSystem :: TestTree
